从MVVM WPF项目中的DataGrid中选择多个项目
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从MVVM WPF项目中的DataGrid中选择多个项目相关的知识,希望对你有一定的参考价值。
如何在MVVM WPF项目中从DataGrid
中选择多个项目?
您只需添加自定义依赖项属性即可:
public class CustomDataGrid : DataGrid
{
public CustomDataGrid ()
{
this.SelectionChanged += CustomDataGrid_SelectionChanged;
}
void CustomDataGrid_SelectionChanged (object sender, SelectionChangedEventArgs e)
{
this.SelectedItemsList = this.SelectedItems;
}
#region SelectedItemsList
public IList SelectedItemsList
{
get { return (IList)GetValue (SelectedItemsListProperty); }
set { SetValue (SelectedItemsListProperty, value); }
}
public static readonly DependencyProperty SelectedItemsListProperty =
DependencyProperty.Register ("SelectedItemsList", typeof (IList), typeof (CustomDataGrid), new PropertyMetadata (null));
#endregion
}
现在你可以在XAML中使用这个dataGrid
:
<Window x:Class="DataGridTesting.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:local="clr-namespace:DataGridTesting.CustomDatagrid"
Title="MainWindow"
Height="350"
Width="525">
<DockPanel>
<local:CustomDataGrid ItemsSource="{Binding Model}"
SelectionMode="Extended"
AlternatingRowBackground="Aquamarine"
SelectionUnit="FullRow"
IsReadOnly="True"
SnapsToDevicePixels="True"
SelectedItemsList="{Binding TestSelected, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</DockPanel>
</Window>
我的ViewModel
:
public class MyViewModel : INotifyPropertyChanged
{
private static object _lock = new object ();
private List<MyModel> _myModel;
public IEnumerable<MyModel> Model { get { return _myModel; } }
private IList _selectedModels = new ArrayList ();
public IList TestSelected
{
get { return _selectedModels; }
set
{
_selectedModels = value;
RaisePropertyChanged ("TestSelected");
}
}
public MyViewModel ()
{
_myModel = new List<MyModel> ();
BindingOperations.EnableCollectionSynchronization (_myModel, _lock);
for (int i = 0; i < 10; i++)
{
_myModel.Add (new MyModel
{
Name = "Test " + i,
Age = i * 22
});
}
RaisePropertyChanged ("Model");
}
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged (string propertyName)
{
var pc = PropertyChanged;
if (pc != null)
pc (this, new PropertyChangedEventArgs (propertyName));
}
}
我的模特:
public class MyModel
{
public string Name { get; set; }
public int Age { get; set; }
}
最后,这是MainWindow
背后的代码:
public partial class MainWindow : Window
{
public MainWindow ()
{
InitializeComponent ();
this.DataContext = new MyViewModel ();
}
}
我希望这个干净的MVVM设计有所帮助。
我要做的是使用Behaviors
创建System.Windows.Interactivity
。您必须在项目中手动引用它。
给定一个不暴露SelectedItems
的控件,例如,(ListBox,DataGrid)
您可以创建类似这样的行为类
public class ListBoxSelectedItemsBehavior : Behavior<ListBox>
{
protected override void OnAttached()
{
AssociatedObject.SelectionChanged += AssociatedObjectSelectionChanged;
}
protected override void OnDetaching()
{
AssociatedObject.SelectionChanged -= AssociatedObjectSelectionChanged;
}
void AssociatedObjectSelectionChanged(object sender, SelectionChangedEventArgs e)
{
var array = new object[AssociatedObject.SelectedItems.Count];
AssociatedObject.SelectedItems.CopyTo(array, 0);
SelectedItems = array;
}
public static readonly DependencyProperty SelectedItemsProperty =
DependencyProperty.Register("SelectedItems", typeof(IEnumerable), typeof(ListBoxSelectedItemsBehavior),
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
public IEnumerable SelectedItems
{
get { return (IEnumerable)GetValue(SelectedItemsProperty); }
set { SetValue(SelectedItemsProperty, value); }
}
}
在你的XAML
我会像这样做Binding
i
是xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
和behaviors
是你的Behavior
类的命名空间
<ListBox>
<i:Interaction.Behaviors>
<behaviors:ListBoxSelectedItemsBehavior SelectedItems="{Binding SelectedItems, Mode=OneWayToSource}" />
</i:Interaction.Behaviors>
假设你的DataContext
的ListBox
在SelectedItems
中具有ViewModel
属性,那么它将自动更新SelectedItems
。你已经封装了从event
订阅的View
,即
<ListBox SelectionChanged="ListBox_SelectionChanged"/>
如果需要,您可以将Behavior
类更改为DataGrid
类型。
我在我的应用中使用此解决方案:
XAML:
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding SelectItemsCommand}" CommandParameter="{Binding Path=SelectedItems,ElementName=TestListView}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
在你的xaml文件的顶部,添加以下代码行:
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
SelectedItems命令是在视图模型中编写的命令类型。
使用的DLL:
System.Windows.Interactivity.dll
使用WPF的默认DataGrid
,不可能使用绑定,因为SelectedItem
-Property可能导致SelectedItems
-Property不是DependencyProperty。
实现目标的一种方法是注册DataGrid的SelectionChanged
-Event以更新存储所选项的ViewModel的属性。
DataGrid的属性SelectedItems属于IList类型,因此您需要将列表中的项目转换为您的特定类型。
C#
public MyViewModel {
get{
return this.DataContext as MyViewModel;
}
}
private void DataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e) {
// ... Get SelectedItems from DataGrid.
var grid = sender as DataGrid;
var selected = grid.SelectedItems;
List<MyObject> selectedObjects = selected.OfType<MyObject>().ToList();
MyViewModel.SelectedMyObjects = selectedObjects;
}
XAML
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<DataGrid
SelectionChanged="DataGrid_SelectionChanged"
/>
</Grid>
</Window>
您可以在模型中添加“IsSelected”属性,并在行中添加一个复选框。
您可以创建可重用的通用基类。这样,您可以从代码和UI中选择行。
这是我希望可以选择的示例类
public class MyClass
{
public string MyString {get; set;}
}
为可选类创建通用基类。设置IsSelected时,INotifyPropertyChanged会更新UI。
public class SelectableItem<T> : System.ComponentModel.INotifyPropertyChanged
{
public SelectableItem(T item)
{
Item = item;
}
public T Item { get; set; }
bool _isSelected;
public bool IsSelected {
get {
return _isSelected;
}
set {
以上是关于从MVVM WPF项目中的DataGrid中选择多个项目的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 MVVM 自动隐藏 WPF 中的 DataGrid 列? [复制]
WPF DataGrid Multiselect启用了虚拟化MVVM
如何防止 WPF DataGrid 在项目更新时取消选择 SelectedItem?
WPF MVVM 将 ComboBox 绑定到 Datagrid 选定项