Проблема выбора WPF ListView с CheckBox - PullRequest
2 голосов
/ 18 августа 2010

У меня есть элемент управления WPF ListView, для которого я динамически создаю столбцы.Один из столбцов оказывается столбцом CheckBox.Когда пользователь непосредственно нажимает на CheckBox, SelectedItem ListView не изменяется.Если бы флажок был объявлен в 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;
    }
}

Итак, мой вопрос заключается в том, как мне создать чекбокс, который будет вызывать выбор строки ListView, когда пользователь нажимает на чекбокс.

Спасибо! РЕДАКТИРОВАТЬ:

Этот вопрос похож, но не имеет динамический кусок: WPF ListView SelectedItem является нулевым

Ответы [ 2 ]

0 голосов
/ 19 августа 2010

Я придумаю решение, которое, кажется, работает для текущей реализации. Изменение основано на обработке события click флажка, а затем на выборе родительского 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;
    }
}
0 голосов
/ 18 августа 2010

Один из способов решения этой проблемы - создать ChildSelectionCompatibleListBoxItem, который наследуется от ListBoxItem и вручную обрабатывает выбор в событиях PreviewMouseDown / Up.Обратите внимание, что становится сложнее, когда вы используете SelectionMode.Extended

. Другой способ - создать производный ListBoxSelectionCompatibleCheckBox, который «экранирует» события мыши, когда родительский ListBoxItem еще не выбран.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...