2010-08-18 92 views
2

我有一个WPF ListView控件,我动态创建列。其中一列恰好是一个CheckBox列。当用户直接点击CheckBox时,ListView的SelectedItem没有改变。如果在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创建一个复选框,将导致ListView的行是选择当用户点击复选框。

谢谢!

编辑:

这个问题是相似的,但不具有动态片:WPF ListView SelectedItem is null

回答

0

解决的一个办法是建立一个“ChildSelectionCompatibleListBoxItem”从“ListBoxItem的”派生,手动处理PreviewMouseDown/Up事件中的选择。请注意,它在使用SelectionMode时变得更加棘手。扩展

另一种方法是创建一个派生的ListBoxSelectionCompatibleCheckBox,当父类ListBoxItem尚未被选中时,它'转义'鼠标事件。

+0

我觉得你的poroposed解决方案更加优雅和灵活。我的解决方案是一个黑客。 – 2010-08-19 14:28:19

+0

是的,我经历了让自己的应用程序适合自己的痛苦过程,并尝试了很多事情后,我结束了上述说明。 – NVM 2010-08-19 17:51:39

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我只需要告诉它被选中。 这应该适用于我的情况下的多选或单选。 编辑: 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 2010-08-19 13:02:46

+0

好的呼叫!我有一种感觉不会很好。 :) – 2010-08-19 14:23:15