Перетаскивание списка WPF без отмены выбора - PullRequest
5 голосов
/ 17 июля 2010

У меня есть объект списка, содержащий файлы в программе. Поведение списка по умолчанию позволяет мне выполнять все операции выбора в списке (нажмите + Shift, чтобы выбрать блок, нажмите + Ctrl для индивидуального выбора членов группы элементов и нажмите, чтобы выбрать один элемент).

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

Если я обработаю событие нажатия «Вниз», изменение выбора происходит в одно и то же время ... только когда начинается перетаскивание, пока нажатие еще не завершено, я знаю, что это перетаскивание по сравнению с изменением выбора.

Вот основной XAML для управления ...

<Window.Resources>
    <Style x:Key="itemstyle" TargetType="{x:Type ListViewItem}">
        <EventSetter Event="PreviewMouseDown" Handler='listView2_MouseLeftButtonDown'/>
    </Style>
</Window.Resources>


<ListView Grid.Column="0" Grid.Row="1" Name="listView2" Margin="5,5,5,5" BorderBrush="LightGray" AllowDrop="True" Drop="listView2_Drop" ItemsSource="{Binding}" ItemContainerStyle="{StaticResource itemstyle}">
                <ListView.View>
                    <GridView>
                        <GridViewColumn Header="Name" Width="100">
                            <GridViewColumn.CellTemplate>
                                <DataTemplate>
                                    <StackPanel Orientation="Horizontal">
                                        <Image Source="{Binding Bmp}"/>
                                        <TextBlock Text="{Binding Name}"/>
                                    </StackPanel>
                                </DataTemplate>
                            </GridViewColumn.CellTemplate>
                        </GridViewColumn>
                        <GridViewColumn Header="Ext" DisplayMemberBinding="{Binding Ext}" Width="Auto"/>
                        <GridViewColumn Header="Size" DisplayMemberBinding="{Binding Size}" Width="Auto"/>
                        <GridViewColumn Header="Date" DisplayMemberBinding="{Binding Date}" Width="Auto"/>
                    </GridView>
                </ListView.View>
            </ListView>

Хорошо, так что я пошел с обработкой событий previewmousedown и предварительного просмотра мыши ... если нажата управляющая клавиша или клавиша Shift, я не устанавливаю флаг дескриптора ... но в противном случае я устанавливаю обработанный аргумент в true (чтобы изменения в выделении не происходили). Затем на событии previewmouseup я завершаю одиночное выделение, устанавливая значение «selected» в значение true (снова только при нажатии shift или ctrl). Так что это вроде работает ... но выбор shift-block не использует какой-либо элемент, который я выбрал программно в качестве допустимой начальной точки для выбора, вместо этого переход к первому элементу, нажатому с помощью клавиши shift или ctrl (даже если я все выбранные элементы были удалены вручную).

Вот источник:

private void listView2_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        if (e.LeftButton == MouseButtonState.Pressed)
        {
            if (!Keyboard.IsKeyDown(Key.LeftCtrl) &&
               !Keyboard.IsKeyDown(Key.RightCtrl) &&
               !Keyboard.IsKeyDown(Key.LeftShift) &&
               !Keyboard.IsKeyDown(Key.RightShift))
            {
                e.Handled = true;
            }
        }
    }

    private void listView2_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        if (e.ChangedButton == MouseButton.Left)
        {
            if (!Keyboard.IsKeyDown(Key.LeftCtrl) &&
               !Keyboard.IsKeyDown(Key.RightCtrl) &&
               !Keyboard.IsKeyDown(Key.LeftShift) &&
               !Keyboard.IsKeyDown(Key.RightShift))
            {

                listView2.SelectedItems.Clear();
                ListViewItem lvi = sender as ListViewItem;
                listView2.SelectedItem = lvi;
                lvi.IsSelected = true;
                e.Handled = true;
            }
        }
    }

1 Ответ

0 голосов
/ 24 февраля 2011

Не так давно была проблема с элементом управления TreeView ... вот как я обошел эту проблему:

private void TreeViewItem_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    // skip mouse clicks on the expander button
    if (e.Source is ToggleButton)
        return;

    // find the original source's parent TreeViewItem
    DependencyObject originalSource = e.OriginalSource as DependencyObject;
    while (originalSource != null)
    {
        TreeViewItem tvi = originalSource as TreeViewItem;
        if (tvi != null)
        {
            IListItem listItem = tvi.Header as IListItem;
            if (listItem != null)
            {
                if (Keyboard.Modifiers == ModifierKeys.Shift)
                    ViewModel.MultiSelectTo(listItem);
                else if (Keyboard.Modifiers == ModifierKeys.Control)
                    ViewModel.ToggleSelection(listItem);
                else
                    ViewModel.Select(listItem);
            }

            // the TreeViewItem is never truly selected... when selected, we manually change it's background color (see xaml)
            tvi.IsSelected = false;
            e.Handled = true;
            break;
        }

        originalSource = VisualTreeHelper.GetParent(originalSource);
    }
}

XAML:

<Style.Triggers>
<DataTrigger Binding="{Binding Selected}" Value="True">
    <Setter Property="Background" Value="#FF3399FF" />
</DataTrigger>
</Style.Triggers>


Интерфейс IListItem - это интерфейс, который реализует мои объекты данных для отображения в моем TreeView.Свойство ViewModel - это мой взгляд DataContext.Кроме того, важен следующий комментарий: «TreeViewItem действительно никогда не выбирается ... при выборе мы вручную изменяем его цвет фона (см. Xaml)».

Итак, в основном, что я сделал, это удалил обработку выбораот элемента управления TreeView, чтобы справиться с этим сам.

Надеюсь, это поможет в любом случае ...

...