我正在使用.NET Framework 4和MVVM Light Toolkit开发WPF应用程序 我创建了一个自定义用户控件,它只包含 DataGrid :
<UserControl
x:Class="PadacEtl.Matcher.Views.LaraDataGrid"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
DataContext="{Binding}">
<DataGrid ItemsSource="{Binding}" SelectionChanged="SelectionChanged">
<DataGrid.Columns>
<DataGridTextColumn Header="Value" Binding="{Binding Model.Value}" />
</DataGrid.Columns>
</DataGrid>
</UserControl>
此控件定义依赖项属性 SelectedItems :
public partial class CustomDataGrid : UserControl
{
public IEnumerable<ItemViewModel> SelectedItems
{
get { return (IEnumerable<ItemViewModel>)GetValue(SelectedItemsProperty); }
set { SetValue(SelectedItemsProperty, value); }
}
public static readonly DependencyProperty SelectedItemsProperty =
DependencyProperty.Register("SelectedItems", typeof(IEnumerable<ItemViewModel>),
typeof(CustomDataGrid), new PropertyMetadata(new List<ItemViewModel>()));
public CustomDataGrid()
{
InitializeComponent();
}
private void SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var dataGrid = sender as DataGrid;
SelectedItems = dataGrid.SelectedItems.Cast<ItemViewModel>();
}
}
最后,此自定义用户控件在视图中使用,定义如下:
<Window x:Class="Project.Views.MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:uc="clr-namespace:Project.Views"
Title="Project"
Height="700" Width="1050"
DataContext="{Binding Source={StaticResource Locator}, Path=Main}">
<Window.Resources>
<ResourceDictionary Source="Styles.xaml" />
</Window.Resources>
<Grid>
<uc:CustomDataGrid DataContext="{Binding Items}"
SelectedItems="{Binding SelectedItems}" />
</Grid>
</Window>
使用相应的 ViewModel :
public class MainViewModel : ViewModelBase
{
public ObservableCollection<ItemViewModel> Items { get; private set; }
private IEnumerable<ItemViewModel> selectedItems = new List<ItemViewModel>();
public IEnumerable<ItemViewModel> SelectedItems
{
get { return selectedItems; }
set
{
if (value != selectedItems)
{
selectedItems = value;
RaisePropertyChanged(() => SelectedItems);
}
}
}
public MainViewModel()
{
//Something useful to feed Items
}
}
我的问题是:当我从 CustomDataGrid 中选择一行或多行时,来自 MainViewModel 的 SelectedItems 是没有更新。我想我没有做好任何事情,但我找不到。
有什么想法吗?
答案 0 :(得分:3)
您必须在SelectedItems
媒体资源上设置双向绑定。你可以在绑定表达式中明确地这样做:
<uc:CustomDataGrid ... SelectedItems="{Binding SelectedItems, Mode=TwoWay}"/>
或者在依赖项属性声明中设置FrameworkPropertyMetadataOptions.BindsTwoWayByDefault标志:
public static readonly DependencyProperty SelectedItemsProperty =
DependencyProperty.Register(
"SelectedItems",
typeof(IEnumerable<ItemViewModel>),
typeof(CustomDataGrid),
new FrameworkPropertyMetadata(
null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
另请注意,将默认属性值设置为新的集合实例是不好的做法,因为该集合将用作属性的所有“实例”的默认值。换句话说,CustomDataGrid的两个实例上的SelectedItems
属性的默认值将是相同的集合对象。如果您向一个项目添加项目,则项目也将包含在另一个项目中。您必须在控件的构造函数中设置默认值。
编辑:在再次查看您的UserControl以及如何绑定其属性之后,我意识到它无法按您设计的方式工作。在绑定声明中设置DataContext
<uc:CustomDataGrid DataContext="{Binding Items}"
SelectedItems="{Binding SelectedItems}"/>
需要显式设置SelectedItems
绑定的绑定源对象,可能就像这个
SelectedItems="{Binding SelectedItems, Source={StaticResource myViewModelInstance}}"
除了Items
属性之外,您的控件应该具有可绑定的ItemsSource
或SelectedItems
。然后你可以简单地编写你的绑定:
<uc:CustomDataGrid DataContext="{StaticResource myViewModelInstance}"
ItemsSource="{Binding Items}" SelectedItems="{Binding SelectedItems}"/>
答案 1 :(得分:0)
将List更改为observablecollection,因为observablecollection实现了INotifyCollectionChanged和INotifyPropertyChanged,其中列表不这样做