我有一个WPF ListView控件,我正在动态创建列。其中一列恰好是CheckBox列。当用户直接单击CheckBox时,ListView的SelectedItem不会更改。如果在XAML中声明了复选框,我会为Click事件添加处理以手动设置选择。但是,我很难过,因为它是一个动态的专栏。
<ListView
SelectionMode="Single"
ItemsSource="{Binding Documents}"
View="{Binding Converter={local:DocumentToGridViewConverter}}" />
转换器接受一个具有与之关联的Properties的对象,有一个名称/值对可以通过索引器引用。
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
答案 0 :(得分:0)
解决此问题的一种方法是创建一个'ChildSelectionCompatibleListBoxItem',它从'ListBoxItem'派生并手动处理PreviewMouseDown / Up事件中的选择。请注意,当您使用SelectionMode.Extended
时,它会变得更加棘手另一种方法是创建派生的ListBoxSelectionCompatibleCheckBox,当尚未选择父ListBoxItem时,它会“转义”鼠标事件。
答案 1 :(得分:0)
我想出了一个似乎适用于当前实现的解决方案。更改的根源在于处理复选框的click事件,然后将父ListViewItem设置为selected。
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;
}
}