【问题标题】:WPF ListView selection issue with CheckBoxCheckBox 的 WPF ListView 选择问题
【发布时间】:2011-03-31 15:13:51
【问题描述】:

我有一个 WPF ListView 控件,我正在为其动态创建列。其中一列恰好是 CheckBox 列。当用户直接单击 CheckBox 时,ListView 的 SelectedItem 不会更改。如果在 XAML 中声明了该复选框,我将添加对 Click 事件的处理以手动设置选择。但是,我很困惑,因为它是一个动态列。

<ListView
    SelectionMode="Single"
    ItemsSource="{Binding Documents}"                    
    View="{Binding Converter={local:DocumentToGridViewConverter}}" />

转换器接收一个具有与之关联的属性的对象,有一个可以通过索引器引用的名称/值对。

public class DocumentToGridViewConverter : MarkupExtension, IValueConverter
{
    private static DocumentToGridViewConverter mConverter;

    public object Convert( object value, Type targetType, object parameter, CultureInfo culture )
    {
        GridView gridView = null;

        Document document = value as Document;
        if( document != null )
        {
            // Create a new grid view.
            gridView = new GridView();

            // Add an isSelected checkbox complete with binding.
            var checkBox = new FrameworkElementFactory( typeof( CheckBox ) );
            gridView.Columns.Add( new GridViewColumn
            {
                Header = string.Empty, // Blank header
                CellTemplate = new DataTemplate { VisualTree = checkBox  },
            } );

            // Add the rest of the columns from the document properties.
            for( int index = 0; index < document.PropertyNames.Length; index++ )
            {
                gridView.Columns.Add( new GridViewColumn
                {
                    Header = document.PropertyNames[index];
                    DisplayMemberBinding = new Binding(
                        string.Format( "PropertyValues[{0}]", index ) )
                } );
            }
        }

        return gridView;
    }

    public object ConvertBack( object value, Type targetType, object parameter, CultureInfo culture )
    {
        throw new NotImplementedException();
    }

    public override object ProvideValue( IServiceProvider serviceProvider )
    {
        if( mConverter == null )
        {
            mConverter = new DocumentToGridViewConverter();
        }
        return mConverter;
    }
}

所以,我的问题是如何动态创建一个 CheckBox,当用户单击 CheckBox 时,它将导致 ListView 行被选中。

谢谢!

编辑:

这个问题类似,但没有动态片段:WPF ListView SelectedItem is null

【问题讨论】:

    标签: c# .net wpf


    【解决方案1】:

    解决此问题的一种方法是创建一个派生自“ListBoxItem”的“ChildSelectionCompatibleListBoxItem”,并在 PreviewMouseDown/Up 事件中手动处理选择。请注意,当您使用 SelectionMode.Extended 时,它会变得更加棘手

    另一种方法是创建一个派生的 ListBoxSelectionCompatibleCheckBox,它在尚未选择父 ListBoxItem 时“转义”鼠标事件。

    【讨论】:

    • 我觉得您的多孔解决方案更加优雅和灵活。我的解决方案是 hack。
    • 是的,我经历了为自己的应用程序正确设置此功能的痛苦过程,在尝试了很多事情后,最终得到了我上面所说的。
    【解决方案2】:

    我想出了一个似乎适用于当前实施的解决方案。更改的根源在于处理复选框的单击事件,然后将父 ListViewItem 设置为选中。

    FrameworkElementFactory checkBox = new FrameworkElementFactory( typeof(CheckBox) );
    checkBox.AddHandler( CheckBox.ClickEvent, new RoutedEventHandler( OnCheckBoxClick ) );
    gridView.Columns.Add( new GridViewColumn
    {
        Header = string.Empty,
        CellTemplate = new DataTemplate { VisualTree = checkBox },
    } );
    

    在事件处理程序中,我调用一个新的扩展方法来查找复选框所在的 ListViewItem。然后,如果它找到 LiveViewItem,我只需告诉它被选中。 在我的情况下,这应该适用于多选或单选。 编辑: NVM 指出这不适用于绝对正确的多选!

    private void OnCheckBoxClick( object sender, RoutedEventArgs e )
    {
        ListViewItem item = ((CheckBox)sender).FindParent<ListViewItem>();
        if( item != null )
        {
            item.IsSelected = true;
        }
    }
    

    这是在链中查找指定类型的父级的扩展方法。

    public static class DependencyObjectExtensions
    {
        public static TItem FindParent<TItem>( this DependencyObject dependencyObject )
            where TItem : class
        {
            TItem parent = null;
    
            DependencyObject possibleParent = dependencyObject;
            while( parent == null && possibleParent != null )
            {
                parent = possibleParent as TItem;
                possibleParent = VisualTreeHelper.GetParent( possibleParent );
            }
    
            return parent;
        }
    }
    

    【讨论】:

    • 您应该使用 SelectionMode.Extended + 'Ctrl+Click'/'Shift+Click' 等进行测试...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多