0

我正在尝试使我的文本标签可拖动,当您在 ac# wpf 应用程序中将其从一个面板拖动到另一个面板时,文本会浮动在所有其他元素之上。

我的标签是由一个包含故事中单词的数组组成的,如下所示:

foreach (string word in lines)
{
   Label myLabel = new Label();
   myLabel.Content = word;
   myLabel.Name = "lbl" + x;
   myLabel.FontSize = 30;
   myLabel.Margin = new Thickness(0, -10, 0, -10);
   myLabel.FontFamily = new FontFamily("Segoe Print");
   myLabel.MouseDown += new MouseButtonEventHandler(myLabel_MouseDown);
   myLabel.MouseMove += new MouseEventHandler(myLabel_MouseMove);
   myLabel.MouseLeftButtonUp += new MouseButtonEventHandler(myLabel_MouseLeftButtonUp);
   myLabel.MouseUp += new MouseButtonEventHandler(myLabel_MouseUp);
   leftPanel.Children.Add(myLabel);
   myLabelWidth.Add(myLabel.ActualWidth);
   x++;
}

在我的活动中,我试图弄清楚什么会将标签从包含面板移到另一个。在 wpf 中,我什至无法理解如何在按住鼠标并移动时将标签位置设置为鼠标位置。

我有一些根本不起作用的东西,但看起来像这样:

void myLabel_MouseMove(object sender, MouseEventArgs s)
{
   Label myLabel = sender as Label
   if(e.LeftButton == MouseButtonState.Pressed)
   {
      myLabel.Left = e.GetPosition(this).X;
      myLabel.Top= e.GetPosition(this).Y;
   }
}

由于距离太远,我还没有真正走得更远。任何帮助表示赞赏。

谢谢。

4

2 回答 2

2

在 WPF 中实现拖放的方法有很多,但没有一个是真正简单的。例如,您可以:

  • Thumbs添加到 Canvas 并实现 dragstart、dragcomplete 和 dragdelta
  • 使用装饰器。好文章在这里
  • 使用 RenderTransform 并创建一个 TranslateTransform 来移动控件。并在您的窗口/用户控件上手动实现 mousedown、mousemove 和 mouseup。

以下代码使用运行时生成的标签的 RenderTransform 属性在用户用鼠标拖动它们时在屏幕上移动它们。我的示例的一个限制是您不能将其他转换应用于您的标签,因为它将被覆盖。考虑使用 TransformGroup。

Xaml

<Window x:Class="WpfApplication2.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525" Background="Gray" PreviewMouseLeftButtonDown="Window_PreviewMouseLeftButtonDown" PreviewMouseMove="Window_PreviewMouseMove" PreviewMouseLeftButtonUp="Window_PreviewMouseLeftButtonUp">
<Grid>
<ItemsControl ItemsSource="{Binding LabelsCollection}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Label HorizontalAlignment="Center" Content="{Binding}"></Label>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</Grid>

背后的代码

public partial class MainWindow : Window, INotifyPropertyChanged
{
    private List<DependencyObject> _hitResultsList = new List<DependencyObject>();
    private Point _currentlyDraggedMouseOffset;
    private Label _currentlyDragged;
    private ObservableCollection<string> _labelsCollection;
    public event PropertyChangedEventHandler PropertyChanged;

    public MainWindow()
    {
        DataContext = this;
        InitializeComponent();
        LabelsCollection = new ObservableCollection<string>();

        for (int i = 1; i <= 10; i++)
        {
            LabelsCollection.Add("Label " + i);
        }
    }

    public ObservableCollection<string> LabelsCollection
    {
        get { return _labelsCollection; }
        set
        {
            _labelsCollection = value;
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs("LabelsCollection"));
            }
        }
    }

    private void Window_PreviewMouseMove(object sender, MouseEventArgs e)
    {
        if (_currentlyDragged != null)
        {                
            var mousePos = e.GetPosition(this);
            _currentlyDragged.RenderTransform = new TranslateTransform(mousePos.X - _currentlyDraggedMouseOffset.X, mousePos.Y - _currentlyDraggedMouseOffset.Y);
        }
    }

    private void Window_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        _currentlyDragged = null;
        ReleaseMouseCapture();
    }

    private void Window_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        CaptureMouse();
        Point pt = e.GetPosition((UIElement)sender);
        _hitResultsList.Clear();

        VisualTreeHelper.HitTest(this, null,
            new HitTestResultCallback(MyHitTestResult),
            new PointHitTestParameters(pt));

        if (_hitResultsList.Count > 0)
        {
            foreach (DependencyObject d in _hitResultsList)
            {
                var parent = VisualTreeHelper.GetParent(d);
                if (parent != null && parent is Label)
                {
                    _currentlyDragged = parent as Label;
                    if (_currentlyDragged.RenderTransform is TranslateTransform)
                    {
                        _currentlyDraggedMouseOffset.X = e.GetPosition(this).X - ((TranslateTransform)_currentlyDragged.RenderTransform).X;
                        _currentlyDraggedMouseOffset.Y = e.GetPosition(this).Y - ((TranslateTransform)_currentlyDragged.RenderTransform).Y;
                    }
                    else
                    {
                        _currentlyDraggedMouseOffset.X = pt.X;
                        _currentlyDraggedMouseOffset.Y = pt.Y;
                    }

                    return;
                }
            }
        }
        _currentlyDragged = null;
    }

    // Return the result of the hit test to the callback. 
    public HitTestResultBehavior MyHitTestResult(HitTestResult result)
    {
        _hitResultsList.Add(result.VisualHit);
        return HitTestResultBehavior.Continue;
    }

}
于 2013-08-16T08:00:21.633 回答
1

在 WPF 拖放中,活动中心位于 DoDragDrop 方法上,如果您想在应用程序中具有拖放功能,则需要使用该方法。

这是一个相对简单的过程(只要你不是正统的 MVVM)开始......

确定您要实施的控制。在他们的白话中,它被称为“DragSource”。并将您的放置区设置为 AllowDrop=true。

然后挂钩控件的 MouseDown 事件并调用 DoDragDrop。之后,就是挂钩四个回调:DragEnter、DragOver、DragLeave 和 Drop。这些方法控制隐喻在用户表面上的可视化方式。

如果您想参考它,这里有一个演练 http://msdn.microsoft.com/en-us/library/za0zx9y0.aspx

如果你是一个正统的 MVVM 人,你可以使用附加的行为来重新设计代码隐藏中的钩子。

于 2013-08-16T08:06:29.300 回答