Операция DragDrop в заголовке столбца WPF Listview с Gridview вызывает тени заголовка столбца при изменении размера - PullRequest
0 голосов
/ 28 мая 2020

Я пытаюсь реализовать перетаскивание для заголовков столбцов ListView, чтобы заголовок столбца можно было перетащить в определенную цель перетаскивания. Пока все работает достаточно хорошо, но я получаю некоторые странные визуальные эффекты после установки обработчика событий PreviewMouseMove и запуска перетаскивания внутри этого обработчика.

Когда мой обработчик на месте, довольно легко воспроизвести проблему:

  1. Щелкните один из заголовков столбца (чтобы он был выбран).
  2. Измените размер одного из столбцов с помощью мыши.

Это приведет к каким-то образом затененное изображение столбца, выбранного на шаге 1 где-то внутри заголовка столбца, а также перемещающееся при изменении размера столбца на шаге 2.

Это выглядит так:

Тень столбца заголовок при изменении размера

Я попытался создать минимальный пример, чтобы воспроизвести это, и придумал следующий код внутри нового приложения WPF:

MainWindow.xaml

<Window x:Class="WpfApp1.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"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <ListView>
            <ListView.View>
                <GridView>
                    <GridView.ColumnHeaderContainerStyle>
                        <Style TargetType="GridViewColumnHeader">
                            <EventSetter Event="PreviewMouseMove" Handler="FrameworkElement_PreviewMouseMove"/>
                        </Style>
                    </GridView.ColumnHeaderContainerStyle>
                    <GridViewColumn Header="Column0"/>
                    <GridViewColumn Header="Column1"/>
                </GridView>
            </ListView.View>
        </ListView>
    </Grid>
</Window>

MainWindow.xaml.cs

using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Media;

namespace WpfApp1
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void FrameworkElement_PreviewMouseMove(object sender, MouseEventArgs e)
        {
            var gripper = FindChild<Thumb>(sender as GridViewColumnHeader, "PART_HeaderGripper");

            if (e.LeftButton == MouseButtonState.Pressed && !gripper.IsMouseOver)
            {

                DataObject data = new DataObject();
                data.SetData(DataFormats.StringFormat, (sender as GridViewColumnHeader).Content?.ToString() ?? "");
                // Inititate the drag-and-drop operation.
                DragDrop.DoDragDrop(this, data, DragDropEffects.Copy | DragDropEffects.Move);
                e.Handled = true;
            }
        }

        public static T FindChild<T>(DependencyObject parent, string childName) where T : DependencyObject
        {
            // Confirm parent and childName are valid. 
            if (parent == null) return null;

            T foundChild = null;

            int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
            for (int i = 0; i < childrenCount; i++)
            {
                var child = VisualTreeHelper.GetChild(parent, i);
                // If the child is not of the request child type child
                T childType = child as T;
                if (childType == null)
                {
                    // recursively drill down the tree
                    foundChild = FindChild<T>(child, childName);

                    // If the child is found, break so we do not overwrite the found child. 
                    if (foundChild != null) break;
                }
                else if (!string.IsNullOrEmpty(childName))
                {
                    var frameworkElement = child as FrameworkElement;
                    // If the child's name is set for search
                    if (frameworkElement != null && frameworkElement.Name == childName)
                    {
                        // if the child's name is of the request name
                        foundChild = (T)child;
                        break;
                    }
                }
                else
                {
                    // child element found.
                    foundChild = (T)child;
                    break;
                }
            }
            return foundChild;
        }
    }
}

Может ли кто-нибудь дать мне подсказку, как я могу в дальнейшем отследить проблему? Я попытался использовать панель отладки WPF, чтобы узнать больше об этой тени столбца сетки, но смог ее выбрать. Когда я комментирую строку DoDragDrop в своем коде, я больше не получаю тени. Должен ли я каким-то образом отменить эту операцию перетаскивания или почему это влияет на поведение при изменении размера?

Приветствуется любая помощь или подсказка.

...