为什么我的依赖属性发送null到我的视图模型

本文关键字:我的 视图 模型 null 我的依赖 属性 为什么 | 更新日期: 2023-09-27 18:02:32

我遇到了一个问题,我有一些困难的诊断。

我已经创建了一个自定义DataGrid对象(如Sandesh在这里的回答中详细介绍的那样),以便能够绑定到数据网格的各种选定项。然而,尽管看起来dependdecyproperty本身在选择更改时获得了正确的值,但视图模型似乎从未接收到更新的值(而是获得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; }
}

为什么我的依赖属性发送null到我的视图模型

您可以互换使用非泛型IList和IList。你有几个选择。

在视图模型中,您可以将属性和字段更改为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);
}