首页 > 解决方案 > 在 SetValue 之后从 DependencyProperty 在 ViewModel 中获取 null

问题描述

我有这个带有 SelectedItems 属性的扩展 ListBox,以便能够在 SelectionMode 设置为 Extended 时获取所选项目。

public class BindableMultiSelectListBox : ListBox
{
    public static new readonly DependencyProperty SelectedItemsProperty =
        DependencyProperty.Register("SelectedItems", typeof(IList), typeof(BindableMultiSelectListBox),
            new PropertyMetadata(default(IList)));

    public new IList SelectedItems
    {
        get => (IList)GetValue(SelectedItemsProperty);
        set => throw new Exception("This property is read-only. To bind to it you must use 'Mode=OneWayToSource'.");
    }

    protected override void OnSelectionChanged(SelectionChangedEventArgs e)
    {
        base.OnSelectionChanged(e);
        SetValue(SelectedItemsProperty, base.SelectedItems);
    }
}

我在这样的视图中使用它:

<usercontrols:BindableMultiSelectListBox SelectedItems="{Binding SelectedDogs, Mode=OneWayToSource}" ItemsSource="{Binding Dogs}" SelectionMode="Extended"/>

并绑定到我的 viewModel 中的 ObservableCollection:

private ObservableCollection<string> _selectedDogs;

public ObservableCollection<string> SelectedDogs
{
    get
    {
        return _selectedDogs;
    }
    set
    {
        _selectedDogs = value;
        OnPropertyChanged(nameof(SelectedDogs));
    }
}

当我调试 OnSelectionChanged base.SelectedItems 具有预期的选定值时,但是当 SelectedDogs 设置器被击中时,该值为空!

我在这里做错了什么?

标签: c#wpfmvvmdependency-properties

解决方案


目标属性应该绑定到源属性。

在视图模型中初始化源集合:

public ObservableCollection<string> SelectedDogs { get; } = new ObservableCollection<string>();

...并在控件中实现同步:

protected override void OnSelectionChanged(SelectionChangedEventArgs e)
{
    base.OnSelectionChanged(e);
    if (SelectedItems != null)
    {
        foreach (var removed in e.RemovedItems)
            SelectedItems.Remove(removed);
        foreach (var added in e.AddedItems)
            SelectedItems.Add(added);
    }
}

XAML:

... SelectedItems="{Binding SelectedDogs}"

如果要设置源属性,则应在控件中初始化集合。


推荐阅读