none
wpf在.net4.0和4.5的情况下,触摸屏测试时不触法drop事件了 RRS feed

  • 问题

  • <Window x:Class="DragDrop.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:DragDrop"
        Title="Window1" Height="400" Width="500">
        <Window.Resources>
            <DataTemplate x:Key="listBoxTemplate" DataType="{x:Type local:DataItem}">
                <TextBlock Text="{Binding Header}"/>
            </DataTemplate>
            <HierarchicalDataTemplate x:Key="treeViewTemplate" DataType="{x:Type local:DataItem}" 
                                      ItemsSource="{Binding Items}">
                <TextBlock Text="{Binding Header}"/>
            </HierarchicalDataTemplate>
        </Window.Resources>
        <Grid x:Name="mTopLevelGrid">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="10"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <ListBox x:Name="mListBox" Grid.Column="0" ItemsSource="{Binding Source={x:Static local:Data.Instance}, Path=ListBoxItems}" ItemTemplate="{StaticResource listBoxTemplate}"/>
            <TreeView x:Name="mTreeView" Grid.Column="2" ItemsSource="{Binding Source={x:Static local:Data.Instance}, Path=TreeViewItems}" ItemTemplate="{StaticResource treeViewTemplate}"
                      AllowDrop="True" DragOver="OnDragOver" Drop="OnDrop"/>
        </Grid>
    </Window>
    

    后台代码:

    using System;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    
    namespace DragDrop
    {
        public partial class Window1 : Window
        {
            public Window1()
            {
                InitializeComponent();
                AttachEvents();
            }
    
            private void AttachEvents()
            {
                mListBox.PreviewMouseMove += OnPreviewListBoxMouseMove;
                mListBox.QueryContinueDrag += OnQueryContinueDrag;
            }
    
            private void OnPreviewListBoxMouseMove(object sender, MouseEventArgs e)
            {
                if (Mouse.LeftButton != MouseButtonState.Pressed)
                    return;
    
                Point pos = e.GetPosition(mListBox);
                HitTestResult result = VisualTreeHelper.HitTest(mListBox, pos);
                if (result == null)
                    return;
    
                ListBoxItem listBoxItem = Utils.FindVisualParent<ListBoxItem>(result.VisualHit); // Find your actual visual you want to drag
                if (listBoxItem == null || listBoxItem.Content != mListBox.SelectedItem || !(mListBox.SelectedItem is DataItem))
                    return;
    
                DragDropAdorner adorner = new DragDropAdorner(listBoxItem);
                mAdornerLayer = AdornerLayer.GetAdornerLayer(mTopLevelGrid); // Window class do not have AdornerLayer
                mAdornerLayer.Add(adorner);
    
                DataItem dataItem = listBoxItem.Content as DataItem;
                DataObject dataObject = new DataObject(dataItem.Clone());
                // Here, we should notice that dragsource param will specify on which 
                // control the drag&drop event will be fired
                System.Windows.DragDrop.DoDragDrop(mListBox, dataObject, DragDropEffects.Copy);
    
                mStartHoverTime = DateTime.MinValue;
                mHoveredItem = null;
                mAdornerLayer.Remove(adorner);
                mAdornerLayer = null;
                e.Handled = false;
            }
    
            private void OnQueryContinueDrag(object sender, QueryContinueDragEventArgs e)
            {
                mAdornerLayer.Update();
    
                UpdateTreeViewExpandingState();
            }
    
            private void OnDragOver(object sender, DragEventArgs e)
            {
                e.Effects = DragDropEffects.None;
    
                Point pos = e.GetPosition(mTreeView);
                HitTestResult result = VisualTreeHelper.HitTest(mTreeView, pos);
                if (result == null)
                    return;
    
                TreeViewItem selectedItem = Utils.FindVisualParent<TreeViewItem>(result.VisualHit);
                if (selectedItem != null)
                    selectedItem.IsSelected = true;
    
                e.Effects = DragDropEffects.Copy;
            }
    
            private void OnDrop(object sender, DragEventArgs e)
            {
                Point pos = e.GetPosition(mTreeView);
                HitTestResult result = VisualTreeHelper.HitTest(mTreeView, pos);
                if (result == null)
                    return;
    
                TreeViewItem selectedItem = Utils.FindVisualParent<TreeViewItem>(result.VisualHit);
                if (selectedItem == null)
                    return;
    
                DataItem parent = selectedItem.Header as DataItem;
                DataItem dataItem = e.Data.GetData(typeof(DataItem)) as DataItem;
                if (parent != null && dataItem != null)
                    parent.Items.Add(dataItem);
            }
    
            private void UpdateTreeViewExpandingState()
            {
                Win32.POINT point = new Win32.POINT();
                if (Win32.GetCursorPos(ref point))
                {
                    Point pos = new Point(point.X, point.Y);
                    pos = mTreeView.PointFromScreen(pos);
                    HitTestResult result = VisualTreeHelper.HitTest(mTreeView, pos);
                    if (result != null)
                    {
                        TreeViewItem selectedItem = Utils.FindVisualParent<TreeViewItem>(result.VisualHit);
                        if (selectedItem != null)
                        {
                            if (mHoveredItem != selectedItem)
                            {
                                mHoveredItem = selectedItem;
                                mStartHoverTime = DateTime.Now;
                            }
                            else
                            {
                                if (mHoveredItem.Items.Count > 0 && !mHoveredItem.IsExpanded &&
                                    DateTime.Now - mStartHoverTime > TimeSpan.FromSeconds(2))
                                    mHoveredItem.IsExpanded = true;
                            }
                        }
                    }
                }
            }
    
            DateTime mStartHoverTime = DateTime.MinValue;
            TreeViewItem mHoveredItem = null;
            AdornerLayer mAdornerLayer = null;
        }
    
        internal static class Utils
        {
            public static T FindVisualParent<T>(DependencyObject obj) where T : class
            {
                while (obj != null)
                {
                    if (obj is T)
                        return obj as T;
    
                    obj = VisualTreeHelper.GetParent(obj);
                }
    
                return null;
            }
        }
    }
    
    以上代码在.net3.5的情况下正常拖拽。.net4.0和4.5拖拽没有反应。



    wjm

    2014年8月28日 3:28

全部回复