我有一个包含两个文本框的用户控件,以及一些其他控件。我希望能够将复杂类型拖放到此控件上,并且我希望整个控件成为放置目标,包括合成控件周围的文本框和空间。删除数据后,它将被拆分为组件字段,每个组件字段由用户控件中的控件表示。
我遇到的问题是文本框(如果我将AllowDrop设置为true)正在尝试执行自己的拖放操作,并且将仅单独接受放置数据的文本格式。如果我在文本框中将AllowDrop设置为false,则完全禁用文本框的删除。我可以将我的复杂数据拖到标签,复选框等,它的行为与我期望的完全一样。
此外,其他控件周围的空间似乎不被视为有效的放置目标。
如何使文本框的行为与控件(例如标签,复选框或组合框)一致,以及为什么网格不被视为有效的放置目标?
用户控件的来源:
<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>
和代码背后:
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 {
/// <summary>
/// Interaction logic for CompositeControl.xaml
/// </summary>
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>
C#代码背后:
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 {
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
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 );
}
}
}
答案 0 :(得分:4)
看起来我可以通过单独挂钩文本框的拖放事件来获得我想要的行为:
public CompositeControl() {
InitializeComponent();
PreviewDragEnter += new DragEventHandler(CompositeControl_DragEnter);
PreviewDragOver += new DragEventHandler(CompositeControl_DragEnter);
textBox1.PreviewDragEnter += new DragEventHandler(textBox_PreviewDragEnter);
textBox1.PreviewDragOver += new DragEventHandler(textBox_PreviewDragEnter);
textBox1.PreviewDrop += new DragEventHandler(CompositeControl_Drop);
textBox2.PreviewDragEnter += new DragEventHandler(textBox_PreviewDragEnter);
textBox2.PreviewDragOver += new DragEventHandler(textBox_PreviewDragEnter);
textBox2.PreviewDrop += new DragEventHandler(CompositeControl_Drop);
Drop += new DragEventHandler(CompositeControl_Drop);
}
void textBox_PreviewDragEnter(object sender, DragEventArgs e) {
e.Handled = true;
}
答案 1 :(得分:0)
八年后我在这里说这对我有帮助。 MVVM版本:
<i:Interaction.Triggers>
<i:EventTrigger EventName="PreviewDragEnter">
<ei:CallMethodAction TargetObject="{Binding}" MethodName="TextBoxIgnore"/>
</i:EventTrigger>
<i:EventTrigger EventName="PreviewDragOver">
<ei:CallMethodAction TargetObject="{Binding}" MethodName="TextBoxIgnore"/>
</i:EventTrigger>
<i:EventTrigger EventName="PreviewDrop">
<ei:CallMethodAction TargetObject="{Binding}" MethodName="TextBoxDrop"/>
</i:EventTrigger>
</i:Interaction.Triggers>
public void TextBoxIgnore(object sender, DragEventArgs args)
{
args.Handled = true;
}
public void TextBoxDrop(object sender, DragEventArgs args)
{
// handle the drop here.
}
注意:使用以下内容...
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"