2013-08-16 33 views
0

我试图让我的文本标签拖动,其中文​​本浮动高于所有其他元素,当你从一个面板拖动到另一个在c#wpf应用程序。如何使用c#和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; 
    } 
} 

因为这是如此的遥远,我真的没有得到任何进一步。任何帮助表示赞赏。

谢谢。

回答

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; 
    } 

} 
+0

RenderTransform看起来最像我想找的东西,但我无法弄清楚如何添加它与动态生成的标签一起工作的方式。 –

+0

我添加了一个示例如何使用RenderTransform拖动标签。 – keft

+0

谢谢,我有点慢,但感谢你的工作,我想我可以理解。再次感谢。 –

1

在WPF拖放,活动中心在DoDragDrop方法,以及你需要如果您想要在应用程序中使用拖放功能,请使用它。

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

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

然后钩住控件的MouseDown事件并调用DoDragDrop。之后,这是一个挂钩四个回调的问题:DragEnter,DragOver,DragLeave和Drop。这些方法控制隐喻在用户表面上的可视化。在这里,如果你想引用它http://msdn.microsoft.com/en-us/library/za0zx9y0.aspx

如果一个正统的MVVM的人,你可以使用附加的行为重新设计的代码背后的挂钩

有一个步行通过。

+0

我很确定你描述的方式给出了一个代表拖放的图标。我试图让标签浮动,当你拖动它。我用winforms解决了这个问题,但wpf对我来说毫无意义。 –

+0

@AuntJamaima,拖曳反馈将默认为经典的d&d提示,但完全可以肯定你可以介入和使用任何东西。只要它可以被序列化并且不违反安全性。 –

相关问题