2010-08-18 467 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