为什么我的依赖属性将null发送给我的视图模型?
我遇到了一个问题,我在诊断时遇到了一些麻烦。为什么我的依赖属性将null发送给我的视图模型?
我已经创建了一个自定义的DataGrid对象(详见Sandesh的回答here),以便能够绑定到数据网格的各种选定项目。然而,即使它看起来像DependecyProperty本身在选择更改时获得正确的值,视图模型似乎永远不会接收更新的值(它会变为null)。
自定义DataGrid类:
class CustomDataGrid : DataGrid
{
public CustomDataGrid()
{
this.SelectionChanged += CustomDataGrid_SelectionChanged;
}
void CustomDataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
this.SelectedItemsList = this.SelectedItems;
}
#region SelectedItemsList
// In the setter, the value is a valid List with the correct elements.
// For some reason it doesn't seem to be passed on to the view model.
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(OnSelectedItemsListChanged));
private static void OnSelectedItemsListChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
{
System.Diagnostics.Debug.WriteLine("Test");
}
#endregion
}
XAML文件:
<Window x:Class="Test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Test"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:TestViewModel />
</Window.DataContext>
<Grid>
<local:CustomDataGrid AutoGenerateColumns="True"
SelectionMode="Extended"
SelectionUnit="FullRow"
CanUserAddRows="False"
CanUserDeleteRows="False"
CanUserResizeRows="False"
ItemsSource="{Binding TestModels}"
SelectedItemsList="{Binding Path=SelectedTestModels, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</Grid>
</Window>
视图模型:
class TestViewModel : INotifyPropertyChanged
{
public TestViewModel()
{
TestModels = new List<TestModel>
{
new TestModel { Name = "Test 1", ID = 1 },
new TestModel { Name = "Test 2", ID = 2 },
new TestModel { Name = "Test 3", ID = 3 },
};
}
private IEnumerable<TestModel> _testModels;
public IEnumerable<TestModel> TestModels
{
get { return _testModels; }
set
{
_testModels = value;
OnPropertyChanged();
}
}
private IEnumerable<TestModel> _selectedTestModels;
public IEnumerable<TestModel> SelectedTestModels
{
get { return _selectedTestModels; }
set
{
// Right here I would expect value to have a non-null value... but it's always null
_selectedTestModels = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var propChanged = PropertyChanged;
if (propChanged != null)
propChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
的TestModel类(非常简单的POCO):
class TestModel
{
public string Name { get; set; }
public int ID { get; set; }
}
您可以交替使用非通用IList和IList。你有几个选择。
在您的viewmodel中,您可以将您的属性和字段更改为IList。
private IList _selectedTestModels;
public IList SelectedTestModels
{
get { return _selectedTestModels; }
set
{
_selectedTestModels = value;
OnPropertyChanged();
}
}
或者在您的CustomControl中。
public static readonly DependencyProperty SelectedItemsListProperty = DependencyProperty.Register("SelectedItemsList", typeof(IList<TestModel>), typeof(CustomDataGrid));
public IList<TestModel> SelectedItemsList
{
get { return (IList<TestModel>)GetValue(SelectedItemsListProperty); }
set { SetValue(SelectedItemsListProperty, value); }
}
void CustomDataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
SetCurrentValue(SelectedItemsListProperty, SelectedItems.OfType<TestModel>().ToList());
}
作为一个方面说明,我也相信这一点的代码可能会打破你的约束力。
void CustomDataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
this.SelectedItemsList = this.SelectedItems;
}
尝试使用SetCurrentValue来维持您的绑定。
void CustomDataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
SetCurrentValue(SelectedItemsListProperty, SelectedItems);
}
对不起,它看起来并没有做任何事情。视图模型仍然接收null。 –
我不认为这是你的绑定,我认为你的IList在CustomControl中为null。尝试在你的SelectionChanged事件结束时放置一个断点和下面的代码,我打赌SelectedItemsList也是空的。 var test = SelectedItemsList; –
你是对的。如果在执行'this.SelectedItemsList = this.SelectedItems'调用之后添加该行,'SelectedItemsList'仍然为null,即使'SelectedItems'有效且包含数据。我将如何去解决这个问题? –
在Visual Studio的输出窗口中是否存在任何绑定错误消息? 'IList'可能不能从'IEnumerable'分配。 –
Clemens
没有出现在输出窗口中的错误消息,绑定或其他。此外,如果我将视图模型中'TestModels'和'SelectedTestModels'的类型更改为'IList',我仍会得到一个空值。 –