WPF列表视图拖动而不取消选择

时间:2010-07-16 23:36:18

标签: c# wpf listview mouseevent drag

我有一个包含程序中文件的listview对象。默认的listview行为允许我对列表执行所有选择操作(单击+ 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-selection不使用我以编程方式选择的任何项目作为select的有效起点,而是使用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 :(得分:0)

不久前与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控件中删除选择处理以自行处理。

希望这有助于任何方式...