30 March 2018

An improved version of WPF usercontrol drag and drop tutorial

This is based on Microsoft - Walkthrough: Enabling Drag and Drop on a User Control


















The improved circle usercontrol has a CircleID property

Circle.xaml.cs
 using System.Windows;  
 using System.Windows.Controls;  
 using System.Windows.Input;  
 using System.Windows.Media;  
 namespace WpfApp3  
 {  
   /// <summary>  
   /// Interaction logic for Circle.xaml  
   /// </summary>  
   public partial class Circle : UserControl  
   {  
     private Brush _previousFill = null;  
     public Circle()  
     {  
       InitializeComponent();  
     }  
     public Circle(Circle c)  
     {  
       InitializeComponent();  
       this.circleUI.Height = c.circleUI.Height;  
       this.circleUI.Width = c.circleUI.Height;  
       this.circleUI.Fill = c.circleUI.Fill;  
       this.CircleID = c.CircleID;  
     }  
     public int CircleID  
     {  
       get { return (int)GetValue(CircleIDProperty); }  
       set { SetValue(CircleIDProperty, value); }  
     }  
     public static readonly DependencyProperty CircleIDProperty =  
       DependencyProperty.Register("CircleID", typeof(int), typeof(Circle));  
     protected override void OnDragEnter(DragEventArgs e)  
     {  
       base.OnDragEnter(e);  
       _previousFill = circleUI.Fill;  
       if (e.Data.GetDataPresent(DataFormats.StringFormat))  
       {  
         string dataString = (string)e.Data.GetData(DataFormats.StringFormat);  
         BrushConverter converter = new BrushConverter();  
         if (converter.IsValid(dataString))  
         {  
           Brush newFill = (Brush)converter.ConvertFromString(dataString.ToString());  
           circleUI.Fill = newFill;  
         }  
       }  
     }  
     protected override void OnDragLeave(DragEventArgs e)  
     {  
       base.OnDragLeave(e);  
       circleUI.Fill = _previousFill;  
     }  
     protected override void OnDrop(DragEventArgs e)  
     {  
       base.OnDrop(e);  
       if (e.Data.GetDataPresent(DataFormats.StringFormat))  
       {  
         string dataString = (string)e.Data.GetData(DataFormats.StringFormat);  
         BrushConverter converter = new BrushConverter();  
         if (converter.IsValid(dataString))  
         {  
           Brush newFill = (Brush)converter.ConvertFromString(dataString);  
           circleUI.Fill = newFill;  
           if (e.KeyStates.HasFlag(DragDropKeyStates.ControlKey))  
           {  
             e.Effects = DragDropEffects.Copy;  
           }  
           else  
           {  
             e.Effects = DragDropEffects.Move;  
           }  
         }  
       }  
       e.Handled = true;  
     }  
     protected override void OnDragOver(DragEventArgs e)  
     {  
       base.OnDragOver(e);  
       e.Effects = DragDropEffects.None;  
       if (e.Data.GetDataPresent(DataFormats.StringFormat))  
       {  
         string dataString = (string)e.Data.GetData(DataFormats.StringFormat);  
         BrushConverter converter = new BrushConverter();  
         if (converter.IsValid(dataString))  
         {  
           if (e.KeyStates.HasFlag(DragDropKeyStates.ControlKey ))  
           {  
             e.Effects = DragDropEffects.Copy;  
           }  
           else  
           {  
             e.Effects = DragDropEffects.Move;  
           }  
         }  
       }  
       e.Handled = true;  
     }  
     protected override void OnMouseMove(MouseEventArgs e)  
     {  
       base.OnMouseMove(e);  
       if (e.LeftButton == MouseButtonState.Pressed)  
       {  
         DataObject data = new DataObject();  
         data.SetData(DataFormats.StringFormat, circleUI.Fill.ToString());  
         data.SetData("Double", circleUI.Height);  
         data.SetData("Object", this);  
         data.SetData("CircleID", CircleID);  
         DragDrop.DoDragDrop(this, data, DragDropEffects.Copy | DragDropEffects.Move);  
       }  
     }  
     protected override void OnGiveFeedback(GiveFeedbackEventArgs e)  
     {  
       base.OnGiveFeedback(e);  
       // These Effects values are set in the drop target's  
       // DragOver event handler.  
       if (e.Effects.HasFlag(DragDropEffects.Copy))  
       {  
         Mouse.SetCursor(Cursors.Cross);  
       }  
       else if (e.Effects.HasFlag(DragDropEffects.Move))  
       {  
         Mouse.SetCursor(Cursors.Pen);  
       }  
       else  
       {  
         Mouse.SetCursor(Cursors.No);  
       }  
       e.Handled = true;  
     }  
   }  
 }  

Circle.xaml
 <UserControl x:Class="WpfApp3.Circle" x:Name="CircleControl"  
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"   
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"   
        xmlns:local="clr-namespace:WpfApp3"  
        mc:Ignorable="d"   
        d:DesignHeight="300" d:DesignWidth="300"  
        AllowDrop="True">  
   <Grid>  
     <Grid.RowDefinitions>  
       <RowDefinition />  
       <RowDefinition />  
     </Grid.RowDefinitions>  
     <Label Content="{Binding Path=CircleID, ElementName=CircleControl}" Grid.Row="0" />  
     <Ellipse x:Name="circleUI" Grid.Row="1"  
      Height="100" Width="100"  
      Fill="Blue" />  
   </Grid>  
 </UserControl>  
This version of MainWindow identify the circle usercontrol by CircleID and parent panel by its Name
MainWindow.xaml.cs
 using System.Windows;  
 using System.Windows.Controls;  
 using System.Windows.Media;  
 namespace WpfApp3  
 {  
   /// <summary>  
   /// Interaction logic for MainWindow.xaml  
   /// </summary>  
   public partial class MainWindow : Window  
   {  
     public MainWindow()  
     {  
       InitializeComponent();  
     }  
     private void panel_DragOver(object sender, DragEventArgs e)  
     {  
       if (e.Data.GetDataPresent("Object"))  
       {  
         if (e.KeyStates == DragDropKeyStates.ControlKey )  
         {  
           e.Effects = DragDropEffects.Copy;  
         }  
         else  
         {  
           e.Effects = DragDropEffects.Move;  
         }  
       }  
     }  
     private void panel_Drop(object sender, DragEventArgs e)  
     {  
       string panelName;  
       if (e.Handled == false)  
       {  
         Panel _panel = (Panel)sender;  
         UIElement _element = (UIElement)e.Data.GetData("Object");  
         if (_panel!= null && _element!=null)  
         {  
           panelName = _panel.Name;  
           Panel _parent = (Panel)VisualTreeHelper.GetParent(_element);  
           if (_parent!=null)  
           {  
             if (e.KeyStates ==DragDropKeyStates.ControlKey &&  
               e.AllowedEffects.HasFlag(DragDropEffects.Copy))  
             {  
               Circle _circle = new Circle((Circle)_element);  
               int cid = _circle.CircleID;  
               string s = cid.ToString() + " is in " + panelName;  
               MessageBox.Show(s);  
               _panel.Children.Add(_circle);  
               e.Effects = DragDropEffects.Copy;  
             }  
             else if (e.AllowedEffects.HasFlag(DragDropEffects.Move))  
             {  
               Circle _circle = new Circle((Circle)_element);  
               int cid = _circle.CircleID;  
               string s = cid.ToString() + " is in " + panelName;  
               MessageBox.Show(s);  
               _parent.Children.Remove(_element);  
               _panel.Children.Add(_element);  
               e.Effects = DragDropEffects.Move;  
             }  
           }  
         }  
       }  
     }  
   }  
 }  

MainWindow.xaml
 <Window x:Class="WpfApp3.MainWindow"  
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"  
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"  
     xmlns:local="clr-namespace:WpfApp3"  
     mc:Ignorable="d"  
     Title="MainWindow" Height="350" Width="525">  
   <Grid>  
     <Grid.ColumnDefinitions>  
       <ColumnDefinition />  
       <ColumnDefinition />  
     </Grid.ColumnDefinitions>  
     <StackPanel Grid.Column="0"  
           x:Name="LeftPanel"  
       Background="Beige"  
           AllowDrop="True"  
       DragOver="panel_DragOver"  
       Drop="panel_Drop"  
           >  
       <TextBox Width="Auto" Margin="2"  
        Text="green"/>  
       <local:Circle Margin="2" CircleID="1" />  
       <local:Circle Margin="2" CircleID="2"/>  
     </StackPanel>  
     <StackPanel Grid.Column="1"  
            x:Name="RightPanel"  
       Background="Bisque"  
       AllowDrop="True"  
       DragOver="panel_DragOver"  
       Drop="panel_Drop"     
           >  
     </StackPanel>  
   </Grid>  
 </Window>  

No comments:

Post a Comment