我有一个包含两个文本框和其他一些控件的用户控件。我希望能够将复杂类型拖放到此控件上,并且我希望整个控件成为放置目标,包括复合控件周围的文本框和空间。当数据被删除时,它被拆分成组件字段,每个字段由用户控件中的控件表示。

我遇到的问题是文本框(如果我将 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 );
        }
    }
}

最佳答案

看起来我可以通过单独 Hook 文本框的拖放事件来获得我想要的行为:

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

关于c# - 拖放到具有多个文本框的复合用户控件上,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/4731891/

10-11 22:44
查看更多