I have a user control that contains two text fields, as well as some other controls. I want to be able to drag a complex type onto this control, and I want the whole control to be the target point, including text fields and the space around the composite controls. When data is discarded, it is divided into component fields, each of which is represented by controls in a user control.
The problem I am facing is that the text fields (if I set AllowDrop to true) are trying to do their own drag and drop thing and will individually accept only the text format of the drag and drop data. If I set AllowDrop to false in a text field, this drop is disabled for text fields. I can drag my complex data onto labels, checkboxes, etc., And it behaves exactly as I expect.
In addition, the space around other controls does not appear to be considered a valid target point.
Any ideas on how to make text fields behave like controls (such as labels, check boxes, or combo boxes) and why isn't the grid considered the real purpose of the quotation mark?
Source for user control:
<UserControl x:Class="DragDropTester.CompositeControl"
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"
mc:Ignorable="d"
d:DesignHeight="226" d:DesignWidth="428" AllowDrop="True">
<Grid AllowDrop="True">
<TextBox Height="23" Margin="115,12,12,0" Name="textBox1" VerticalAlignment="Top" AllowDrop="False" />
<Label Content="TextBox 1:" Height="28" HorizontalAlignment="Left" Margin="12,12,0,0" Name="label1" VerticalAlignment="Top" Width="97" />
<TextBox Height="23" Margin="115,41,12,0" Name="textBox2" VerticalAlignment="Top" AllowDrop="False" />
<Label Content="TextBox 2:" Height="28" HorizontalAlignment="Left" Margin="12,41,0,0" Name="label2" VerticalAlignment="Top" Width="97" />
<CheckBox Content="CheckBox" Height="16" Margin="115,70,150,0" Name="checkBox1" VerticalAlignment="Top" />
<ComboBox Height="23" Margin="115,92,12,0" Name="comboBox1" VerticalAlignment="Top" />
</Grid>
</UserControl>
and the code behind:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace DragDropTester {
public partial class CompositeControl : UserControl {
public CompositeControl() {
InitializeComponent();
PreviewDragEnter += new DragEventHandler(CompositeControl_DragEnter);
this.PreviewDragOver += new DragEventHandler(CompositeControl_DragEnter);
Drop += new DragEventHandler(CompositeControl_Drop);
}
void CompositeControl_Drop(object sender, DragEventArgs e) {
var complex = e.Data.GetData("ComplexDragData") as ComplexDragData;
if (complex != null) {
this.textBox1.Text = complex.Text1;
this.textBox2.Text = complex.Text2;
this.checkBox1.IsChecked = complex.BoolValue;
}
}
void CompositeControl_DragEnter(object sender, DragEventArgs e) {
var complex = e.Data.GetData("ComplexDragData") as ComplexDragData;
if (complex != null) {
e.Effects = DragDropEffects.Link;
} else {
e.Effects = DragDropEffects.None;
}
e.Handled = true;
}
}
}
, ...
XAML:
<Window x:Class="DragDropTester.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:src="clr-namespace:DragDropTester"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="40" />
</Grid.RowDefinitions>
<src:CompositeControl />
<Label Content="Drag Source" Grid.Row="1" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Margin="5" Background="LightGray" Name="lblDragSource" />
</Grid>
</Window>
# :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace DragDropTester {
public partial class MainWindow : Window {
private Point _startPoint;
private bool _IsDragging;
public MainWindow() {
InitializeComponent();
lblDragSource.PreviewMouseLeftButtonDown += new MouseButtonEventHandler(lblDragSource_PreviewMouseLeftButtonDown);
lblDragSource.PreviewMouseMove += new MouseEventHandler(lblDragSource_PreviewMouseMove);
}
void lblDragSource_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) {
_startPoint = e.GetPosition(sender as IInputElement);
}
void lblDragSource_PreviewMouseMove(object sender, MouseEventArgs e) {
if (_startPoint == null) {
return;
}
if (e.LeftButton == MouseButtonState.Pressed && !_IsDragging) {
Point position = e.GetPosition(sender as IInputElement);
if (Math.Abs(position.X - _startPoint.X) > SystemParameters.MinimumHorizontalDragDistance || Math.Abs(position.Y - _startPoint.Y) > SystemParameters.MinimumVerticalDragDistance) {
StartDrag(sender as DependencyObject);
}
}
}
private void StartDrag(DependencyObject dragSource) {
var data = new DataObject();
var dragData = new ComplexDragData { Text1 = "This is text1", Text2 = "This is text2", BoolValue = true };
data.SetData("ComplexDragData", dragData);
data.SetData(DataFormats.Text, dragData.ToString());
try {
_IsDragging = true;
DragDrop.DoDragDrop(dragSource, data, DragDropEffects.Copy | DragDropEffects.Link);
} finally {
_IsDragging = false;
}
}
}
public class ComplexDragData {
public String Text1 { get; set; }
public String Text2 { get; set; }
public bool BoolValue { get; set; }
public override string ToString() {
return string.Format("text1: {0} text2: {1} Bool: {2}", Text1, Text2, BoolValue );
}
}
}