it-swarm.com.de

Machen Sie das WPF-Fenster ziehbar, egal auf welches Element Sie klicken

Meine Frage ist zweifach und ich hoffe, es gibt einfachere Lösungen für beide, die vonWPFbereitgestellt werden, und nicht für die Standardlösungen von WinForms (die Christophe Geers vor dieser Klärung zur Verfügung gestellt hat).

Gibt es eine Möglichkeit, Fenster ziehbar zu machen, ohne dass Mausklicks und Ereignisse per Drag & Drop erfasst und verarbeitet werden? Ich meine, das Fenster kann von der Titelleiste gezogen werden, aber wenn ich ein Fenster so eingestellt habe, dass es noch kein Fenster haben soll, gibt es eine Möglichkeit, die Ereignisse einfach an die Griffleiste der Titelleiste zu lenken ?

Gibt es eine Möglichkeit, einen Ereignishandler auf alle Elemente im Fenster anzuwenden? Lassen Sie das Fenster wie ziehen, unabhängig von dem Element, auf das der Benutzer klicken und ziehen kann. Offensichtlich ohne den Handler manuell hinzuzufügen, für jedes einzelne Element. Einfach mal irgendwo machen?

94
Alex K

Übernehmen Sie das folgende MouseDown-Ereignis Ihrer Window

private void Window_MouseDown(object sender, MouseButtonEventArgs e)
{
    if (e.ChangedButton == MouseButton.Left)
        this.DragMove();
}

Auf diese Weise können Benutzer das Fenster ziehen, wenn sie auf ein Steuerelement klicken/ziehen. AUSNAHME für Steuerelemente, die das MouseDown-Ereignis (e.Handled = true) verwenden.

Sie können PreviewMouseDown anstelle von MouseDown verwenden, das Drag-Ereignis frisst jedoch das Click-Ereignis, sodass Ihr Fenster nicht mehr auf Klickereignisse mit der linken Maustaste reagiert. Wenn Sie wirklich in der Lage waren, das Formular aus einem beliebigen Steuerelement anklicken und ziehen zu können, könnten Sie wahrscheinlich PreviewMouseDown verwenden, einen Zeitgeber zum Starten des Ziehvorgangs starten und den Vorgang abbrechen, wenn das MouseUp-Ereignis innerhalb von X Millisekunden ausgelöst wird.

239
Rachel

wenn das wpf-Formular unabhängig davon, wo es angeklickt wurde, ziehbar sein muss, verwenden Sie als Delegat die DragMove () - Methode für das Windows-Ereignis onload oder das grid load-Ereignis

private void Grid_Loaded(object sender, RoutedEventArgs 
{
      this.MouseDown += delegate{DragMove();};
}
7
Pranavan Maru

Manchmal haben wir keinen Zugriff auf Window, z. Wenn wir DevExpress verwenden, steht nur eine UIElement zur Verfügung.

Schritt 1: Fügen Sie die angefügte Eigenschaft hinzu

Die Lösung ist zu:

  1. In MouseMove-Ereignisse einhängen;
  2. Durchsuchen Sie den visuellen Baum, bis wir das erste übergeordnete Element Window finden.
  3. Rufen Sie .DragMove() für unsere neu entdeckte Window auf.

Code:

using System.Windows;
using System.Windows.Input;
using System.Windows.Media;

namespace DXApplication1.AttachedProperty
{
    public class EnableDragHelper
    {
        public static readonly DependencyProperty EnableDragProperty = DependencyProperty.RegisterAttached(
            "EnableDrag",
            typeof (bool),
            typeof (EnableDragHelper),
            new PropertyMetadata(default(bool), OnLoaded));

        private static void OnLoaded(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
        {
            var uiElement = dependencyObject as UIElement;
            if (uiElement == null || (dependencyPropertyChangedEventArgs.NewValue is bool) == false)
            {
                return;
            }
            if ((bool)dependencyPropertyChangedEventArgs.NewValue  == true)
            {
                uiElement.MouseMove += UIElementOnMouseMove;
            }
            else
            {
                uiElement.MouseMove -= UIElementOnMouseMove;
            }

        }

        private static void UIElementOnMouseMove(object sender, MouseEventArgs mouseEventArgs)
        {
            var uiElement = sender as UIElement;
            if (uiElement != null)
            {
                if (mouseEventArgs.LeftButton == MouseButtonState.Pressed)
                {
                    DependencyObject parent = uiElement;
                    int avoidInfiniteLoop = 0;
                    // Search up the visual tree to find the first parent window.
                    while ((parent is Window) == false)
                    {
                        parent = VisualTreeHelper.GetParent(parent);
                        avoidInfiniteLoop++;
                        if (avoidInfiniteLoop == 1000)
                        {
                            // Something is wrong - we could not find the parent window.
                            return;
                        }
                    }
                    var window = parent as Window;
                    window.DragMove();
                }
            }
        }

        public static void SetEnableDrag(DependencyObject element, bool value)
        {
            element.SetValue(EnableDragProperty, value);
        }

        public static bool GetEnableDrag(DependencyObject element)
        {
            return (bool)element.GetValue(EnableDragProperty);
        }
    }
}

Schritt 2: Fügen Sie einem Element die angefügte Eigenschaft hinzu, damit das Fenster gezogen werden kann

Der Benutzer kann das gesamte Fenster ziehen, indem er auf ein bestimmtes Element klickt, wenn wir diese angefügte Eigenschaft hinzufügen:

<Border local:EnableDragHelper.EnableDrag="True">
    <TextBlock Text="Click me to drag this entire window"/>
</Border>

Anhang A: Optionales erweitertes Beispiel

In diesem Beispiel aus DevExpress ersetzen wir die Titelleiste eines Docking-Fensters durch unser eigenes graues Rechteck. Wenn der Benutzer das graue Rechteck anklickt und zieht, wird das Fenster normal gezogen:

<dx:DXWindow x:Class="DXApplication1.MainWindow" Title="MainWindow" Height="464" Width="765" 
    xmlns:dx="http://schemas.devexpress.com/winfx/2008/xaml/core" 
    xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml" 
    xmlns:dxdo="http://schemas.devexpress.com/winfx/2008/xaml/docking" 
    xmlns:local="clr-namespace:DXApplication1.AttachedProperty"
    xmlns:dxdove="http://schemas.devexpress.com/winfx/2008/xaml/docking/visualelements"
    xmlns:themeKeys="http://schemas.devexpress.com/winfx/2008/xaml/docking/themekeys">

    <dxdo:DockLayoutManager FloatingMode="Desktop">
        <dxdo:DockLayoutManager.FloatGroups>
            <dxdo:FloatGroup FloatLocation="0, 0" FloatSize="179,204" MaxHeight="300" MaxWidth="400" 
                             local:TopmostFloatingGroupHelper.IsTopmostFloatingGroup="True"                             
                             >
                <dxdo:LayoutPanel ShowBorder="True" ShowMaximizeButton="False" ShowCaption="False" ShowCaptionImage="True" 
                                  ShowControlBox="True" ShowExpandButton="True" ShowInDocumentSelector="True" Caption="TradePad General" 
                                  AllowDock="False" AllowHide="False" AllowDrag="True" AllowClose="False"
                                  >
                    <Grid Margin="0">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition Height="*"/>
                        </Grid.RowDefinitions>
                        <Border Grid.Row="0" MinHeight="15" Background="#FF515151" Margin="0 0 0 0"
                                                                  local:EnableDragHelper.EnableDrag="True">
                            <TextBlock Margin="4" Text="General" FontWeight="Bold"/>
                        </Border>
                        <TextBlock Margin="5" Grid.Row="1" Text="Hello, world!" />
                    </Grid>
                </dxdo:LayoutPanel>
            </dxdo:FloatGroup>
        </dxdo:DockLayoutManager.FloatGroups>
    </dxdo:DockLayoutManager>
</dx:DXWindow>

Haftungsausschluss: Ich bin nicht mit DevExpress verbunden. Diese Technik funktioniert mit jedem Benutzerelement, einschließlich Standard WPF oder Telerik (ein weiterer guter WPF - Bibliotheksanbieter).

4
Contango
private void Window_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton == MouseButton.Left)
    this.DragMove();
}

In einigen Fällen wird eine Ausnahme ausgelöst (d. H., Wenn Sie im Fenster ein anklickbares Bild haben, das beim Anklicken ein Meldungsfeld öffnet. Wenn Sie das Meldungsfeld verlassen, wird eine Fehlermeldung angezeigt)

private void Window_MouseDown(object sender, MouseButtonEventArgs e)
{
if (Mouse.LeftButton == MouseButtonState.Pressed)
            this.DragMove();
}

Sie sind sich also sicher, dass die linke Taste in diesem Moment gedrückt wird.

3
Nick

Sie können ein Formular per Drag & Drop verschieben, indem Sie auf eine beliebige Stelle im Formular klicken, nicht nur auf die Titelleiste. Dies ist praktisch, wenn Sie ein randloses Formular haben.

Dieser Artikel zu CodeProject zeigt eine mögliche Lösung, um dies zu implementieren:

http://www.codeproject.com/KB/cs/DraggableForm.aspx

Grundsätzlich wird ein Nachkomme des Formulartyps erstellt, in dem die Mauszeiger nach unten, nach oben und nach unten verschoben werden. 

  • Maus runter: Position merken 
  • Maus verschieben: Neuen Ort speichern
  • Maus hoch: Formular an neuer Stelle positionieren

Und hier ist eine ähnliche Lösung, die in einem Video-Tutorial erläutert wird:

http://www.youtube.com/watch?v=tJlY9aX73Vs

Ich würde das Ziehen des Formulars nicht zulassen, wenn ein Benutzer auf ein Steuerelement in diesem Formular klickt. Benutzer erhalten unterschiedliche Ergebnisse, wenn sie auf verschiedene Steuerelemente klicken. Wenn sich mein Formular plötzlich bewegt, weil ich auf ein Listenfeld, eine Schaltfläche, ein Etikett usw. geklickt habe. das wäre verwirrend.

2

Das ist alles nötig! 

private void UiElement_MouseMove(object sender, MouseEventArgs e)
    {
        if (e.LeftButton == MouseButtonState.Pressed)
        {
            if (this.WindowState == WindowState.Maximized) // In maximum window state case, window will return normal state and continue moving follow cursor
            {
                this.WindowState = WindowState.Normal;
                Application.Current.MainWindow.Top = 3;// 3 or any where you want to set window location affter return from maximum state
            }
            this.DragMove();
        }
    }
1
loi.efy
<Window
...
WindowStyle="None" MouseLeftButtonDown="WindowMouseLeftButtonDown"/>
<x:Code>
    <![CDATA[            
        private void WindowMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            DragMove();
        }
    ]]>
</x:Code>

Quelle

0

Die nützlichste Methode, sowohl für WPF als auch für Windows, WPF-Beispiel:

    [DllImport("user32.dll")]
    public static extern IntPtr SendMessage(IntPtr hWnd, int wMsg, int wParam, int lParam);

    public static void StartDrag(Window window)
    {
        WindowInteropHelper helper = new WindowInteropHelper(window);
        SendMessage(helper.Handle, 161, 2, 0);
    }
0
dexiang

Wie bereits bei @ fjch1997 erwähnt, ist es praktisch, ein Verhalten zu implementieren. Hier ist die Kernlogik die gleiche wie in @ loi.efys answer :

public class DragMoveBehavior : Behavior<Window>
{
    protected override void OnAttached()
    {
        AssociatedObject.MouseMove += AssociatedObject_MouseMove;
    }

    protected override void OnDetaching()
    {
        AssociatedObject.MouseMove -= AssociatedObject_MouseMove;
    }

    private void AssociatedObject_MouseMove(object sender, MouseEventArgs e)
    {
        if (e.LeftButton == MouseButtonState.Pressed && sender is Window window)
        {
            // In maximum window state case, window will return normal state and
            // continue moving follow cursor
            if (window.WindowState == WindowState.Maximized)
            {
                window.WindowState = WindowState.Normal;

                // 3 or any where you want to set window location after
                // return from maximum state
                Application.Current.MainWindow.Top = 3;
            }

            window.DragMove();
        }
    }
}

Verwendungszweck:

<Window ...
        xmlns:h="clr-namespace:A.Namespace.Of.DragMoveBehavior"
        xmlns:i="http://schemas.Microsoft.com/expression/2010/interactivity">
    <i:Interaction.Behaviors>
        <h:DragMoveBehavior />
    </i:Interaction.Behaviors>
    ...
</Window>
0
stop-cran