【发布时间】:2015-11-18 05:21:19
【问题描述】:
我创建了一个包装 DataGrid 的 UserControl1(这是为了测试目的而简化的,实际场景涉及第三方控件但问题是相同的)。 UserControl1 在测试应用程序的 MainWindow 中使用,如下所示:
<test:UserControl1 ItemsSource="{Binding People,Mode=OneWay,ElementName=Self}"
SelectedItems="{Binding SelectedPeople, Mode=TwoWay, ElementName=Self}"/>
一切都按预期工作,除了在 DataGrid 中选择一行时,SelectedPeople 属性始终设置为 null。
行选择流程大致为:UserControl1.DataGrid -> UserControl1.DataGrid_OnSelectionChanged -> UserControl1.SelectedItems -> MainWindow.SelectedPeople
调试显示带有从 DataGrid 中选择的项目的 IList 正在传递给 SelectedItems 依赖项属性的 SetValue 调用。但是当随后调用 SelectedPeople 设置器(作为绑定过程的一部分)时,传递给它的值始终为 null。
这是相关的 UserControl1 XAML:
<Grid>
<DataGrid x:Name="dataGrid" SelectionChanged="DataGrid_OnSelectionChanged" />
</Grid>
在 UserControl1 的代码隐藏中是 SelectedItems 依赖属性和 DataGrid SelectionChanged 处理程序的以下定义:
public static readonly DependencyProperty SelectedItemsProperty = DependencyProperty.Register("SelectedItems", typeof(IList), typeof(UserControl1), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnSelectedItemsChanged));
public IList SelectedItems
{
get { return (IList)GetValue(SelectedItemsProperty); }
set
{
SetValue(SelectedItemsProperty, value);
}
}
private bool _isUpdatingSelectedItems;
private static void OnSelectedItemsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var ctrl = d as UserControl1;
if ((ctrl != null) && !ctrl._isUpdatingSelectedItems)
{
ctrl._isUpdatingSelectedItems = true;
try
{
ctrl.dataGrid.SelectedItems.Clear();
var selectedItems = e.NewValue as IList;
if (selectedItems != null)
{
var validSelectedItems = selectedItems.Cast<object>().Where(item => ctrl.ItemsSource.Contains(item) && !ctrl.dataGrid.SelectedItems.Contains(item)).ToList();
validSelectedItems.ForEach(item => ctrl.dataGrid.SelectedItems.Add(item));
}
}
finally
{
ctrl._isUpdatingSelectedItems = false;
}
}
}
private void DataGrid_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (!_isUpdatingSelectedItems && sender is DataGrid)
{
_isUpdatingSelectedItems = true;
try
{
var x = dataGrid.SelectedItems;
SelectedItems = new List<object>(x.Cast<object>());
}
finally
{
_isUpdatingSelectedItems = false;
}
}
}
这是 MainWindow 代码隐藏中 SomePeople 的定义:
private ObservableCollection<Person> _selectedPeople;
public ObservableCollection<Person> SelectedPeople
{
get { return _selectedPeople; }
set { SetProperty(ref _selectedPeople, value); }
}
public class Person
{
public Person(string first, string last)
{
First = first;
Last = last;
}
public string First { get; set; }
public string Last { get; set; }
}
【问题讨论】:
-
我可以知道 SelectedPeople 的类型是什么吗?
标签: c# wpf data-binding wpf-controls