Announcement

Collapse
No announcement yet.

WPF Popup an Mauszeiger binden

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • WPF Popup an Mauszeiger binden

    Moin,

    Es gibt haufenweise Erklärungen dazu im Netz, aber so richtig will keiner bei mir funktionieren.

    Ich versuche bei einer Drag&Drop Sortierung in einem DataGrid ein Popup am Mauszeiger mitlaufen zu lassen. Ich scheitere aber daran, dass das Popup dem Mauszeiger folgt.
    Wie gesagt habe ich schon einiges ausprobiert und habe den bisher vielversprechendsten Erfolg bei dieser Variante:

    Code:
    <Popup x:Name="DragDropPopup" IsHitTestVisible="False" Placement="Custom" PlacementTarget="{Binding ElementName=dgItemsList}" AllowsTransparency="True">
        <Border BorderBrush="#666" BorderThickness="2" Background="#0378DC" Opacity=".75" CornerRadius="8">
            <StackPanel Orientation="Horizontal" Margin="10 5">
                <Image Margin="0 0 10 0" Source="{Binding FileItemDragDropSortImage}" Height="25"/>
                <TextBlock Text="{Binding FileListDragDropCurrentItemLabel}" VerticalAlignment="Center" FontSize="18" FontWeight="DemiBold" Foreground="#fff"/>
            </StackPanel>
        </Border>
    </Popup>
    Dann habe ich mir eine Methode aus dem Internet angesehen und etwas angepasst:
    Code:
            public CustomPopupPlacement[] placementForPopup(System.Windows.Size popupSize, System.Windows.Size targetSize, System.Windows.Point offset)
            {
                return new CustomPopupPlacement[]
                {
                    new CustomPopupPlacement( new System.Windows.Point(ContextModel.MousePosition.X, ContextModel.MousePosition.Y) , PopupPrimaryAxis.Vertical )
                    , new CustomPopupPlacement( new System.Windows.Point(ContextModel.MousePosition.X, ContextModel.MousePosition.Y) , PopupPrimaryAxis.Horizontal )
                };
            }
    Im ContextModel.MousePosition ist die aktuelle Mausposition hinterlegt.
    Wenn ich jetzt die Binding-Source für den Textblock aus dem Popup mit den Koordinaten versehe ( was ich testweise getan hatte ) funktioniert es einwandfrei:
    Code:
                // Dieser Code steckt in dem MouseMove Handler für das DataGrid!
                ContextModel.MousePosition = e.GetPosition(dgItemsList);
                ContextModel.FileListDragDropCurrentItemLabel = $"{e.GetPosition(this).X} , {e.GetPosition(this).Y}";
                DragDropPopup.CustomPopupPlacementCallback = new CustomPopupPlacementCallback(placementForPopup);
    Die Freude war groß, zerschlug sich allerdings schnell wieder, als ich die mittlere Zeile entfernt hatte, die eigentlich nur einen String befüllt und nichts mit der Position an sich zu tun hat.
    Das Popup bleibt nun am ersten erkannten Mauszeigerpunkt stehen, egal wohin ich die Maus bewege.
    Nehme ich die Zeile wieder rein, läuft das Popup sauber mit, hat aber den falschen Inhalt im Textblock.

    Die Invalidate-Methoden habe ich auch schon probiert, aber es ändert sich nichts. Das Popup folgt der Maus nur, wenn ich den String anpasse:
    Code:
    ContextModel.FileListDragDropCurrentItemLabel = $"{e.GetPosition(this).X} , {e.GetPosition(this).Y}";
    Ich kann mir das grad nicht erklären und hoffe auf Hinweise vn euch.
    Danke
    PHP rocks!
    Eine Initiative der PHP Community

  • #2
    Ich habe festgestellt, dass es mit
    Code:
    DragDropPopup.HorizontalOffset = e.GetPosition(dgItemsList).X;
    DragDropPopup.VerticalOffset = e.GetPosition(dgItemsList).Y;
    grundsätzlich funktioniert, allerdings ist das Popup stark versetzt, sowohl nach X als auch nach Y.
    Eine statische Abweichung konnte ich nicht feststellen, denn der Versatz ist unterschiedlich je nach dem welche DataGridRow ich zum Verschieben wo anpacke. Fasse ich die DataGridRow ziemlich weit links an, ist der horizontale Versatz sehr gering, je weiter ich rechts anfasse, ist der Versatz umso größer.
    Dasselbe gilt für den vertikalen Versatz, da kommt es hauptsächlich darauf an, welche DataGridRow ich anfasse. Je größer der RowIndex, desto größer der Versatz.

    Hat da jemand evtl. einen Tipp, wovon das abhängig ist?
    Ich müsste nur entsprechende Werte abziehen, dann passt alles.

    Danke
    PHP rocks!
    Eine Initiative der PHP Community

    Comment


    • #3
      Versuchst du das ein einem High DPI Monitor? Das Verhalten klingt nach dem üblichen Zoom nicht berücksichtigt (wo auch immer würde vermuten das das WPF eigentlich aus sich selbst heraus richtig macht). Wenn das für 100% Zoom geschrieben ist aber du zum Beispiel deinen Monitor bei 150% betreibst hast du immer einen Faktor von 1.5 drin der nach recht/unten zu einer wachsenden absoluten Abweichung führt.
      Laut Doku wäre am einfachsten sowas
      Code:
      DragDropPopup.Placement = PlacementMode.MousePoint; DragDropPopup.HorizontalOffset = 0; DragDropPopup.VerticalOffset = 0;
      Im Xaml hast du aber Placement bereits auf Custom gesetzt. Hatte vielleicht Gründe.

      Comment


      • #4
        Danke für Deine Rückmeldung!

        Ich habe gestern alles heruntergefahren, inkl. meiner Gedanken dazu und heute mal mit frischen Erkenntnissen und neuen Suchergebnissen jongliert.
        Mein Fehler lag wohl der falschen Kombination von Placement und PlacementTarget.

        Wie es jetzt funktioniert:
        Code:
        <Grid x:Name="gridMain" MouseMove="evh_PopupPositioning">
        
            ...
            <!-- some other stuff -->
            ...
        
            <Popup x:Name="DragDropPopup" IsHitTestVisible="False" Placement="Relative" PlacementTarget="{Binding ElementName=gridMain}" HorizontalOffset="0" VerticalOffset="0" AllowsTransparency="True">
                <Border BorderBrush="#666" BorderThickness="2" Background="#0378DC" Opacity=".75" CornerRadius="8">
                    <StackPanel Orientation="Horizontal" Margin="10 5">
                        <Image Margin="0 0 10 0" Source="{Binding FileItemDragDropSortImage}" Height="25"/>
                        <TextBlock Text="{Binding FileListDragDropCurrentItemLabel}" VerticalAlignment="Center" FontSize="18" FontWeight="DemiBold" Foreground="#fff"/>
                    </StackPanel>
                </Border>
            </Popup>
        </Grid>
        Code:
        private void evh_PopupPositioning(object sender, MouseEventArgs e)
        {
            if (e.LeftButton != MouseButtonState.Pressed)
                return;
        
            Point mouse_pos = e.GetPosition(gridMain);
            DragDropPopup.HorizontalOffset = mouse_pos.X;
            DragDropPopup.VerticalOffset = mouse_pos.Y;
        }
        Der Hinweis mit dem Zoom Faktor ist aber interessant, das beobachte ich trotzdem mal.
        So funktioniert es zumindest einwandfrei schon mal bei Standard-Einstellungen.
        PHP rocks!
        Eine Initiative der PHP Community

        Comment

        Working...
        X