2010-08-18 3 views
2

У меня есть элемент управления ListView WPF, для которого я динамически создаю столбцы. Один из столбцов - столбец CheckBox. Когда пользователь непосредственно нажимает на CheckBox, SelectedItem ListView не изменяется. Если бы флажок был установлен в XAML, я бы добавил обработку события Click, чтобы вручную установить выбор. Тем не менее, я сильно обеспокоен тем, что это динамический столбец.WPF ListView проблема выбора с CheckBox

<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; 
    } 
} 

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

Спасибо!

EDIT:

Этот вопрос похожи, но не имеет динамическую часть: WPF ListView SelectedItem is null

ответ

0

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

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

+0

Я чувствую, что ваше поположенное решение намного элегантнее и гибко. Мое решение - взлом. –

+0

Да, я прошел через болезненный процесс получения этого права для своего собственного приложения, и после того, как я попробовал немало вещей, я закончил с тем, что я сказал выше. – NVM

0

Я придумал решение, которое, похоже, работает для текущей реализации. Это изменение связано с обработкой события щелчка флажка, а затем для установки родительского списка 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 я просто должен сказать ему, чтобы выбрать. Это должно работать с несколькими выборами или одним выбором в моем случае. EDIT: 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

Вы должны проверить его с помощью SelectionMode.Extended + «Ctrl + Click»/«Shift + Click» и т. Д. ... – NVM

+0

Хороший звонок! У меня такое чувство, что это не сработает. :) –

Смежные вопросы