如何将子类型的集合绑定到依赖项 属性

How to bind a collection of a subtype to a dependency property

我正在 WPF 中创建一个 UserControl,它可以用于 IMyNode 类型的任何对象。基本上,它通过依赖项 属性 接收 ObservableCollection,向其注册并执行一些操作。

在我的一个用例中,我在一个使用(并且需要)SomeSpecificNode 的 ObservableCollection 的控件中使用。 SomeSpecificNodeIMyNode.

的实现

目前,我有一个绑定错误:

System.Windows.Data Error: 1 : Cannot create default converter to perform 'one-way' conversions between types 'System.Collections.ObjectModel.ObservableCollection`1[SomeSpecificNode]' and 'System.Collections.ObjectModel.ObservableCollection`1[IMyNode]'. 

我明白为什么会这样,它不知道如何自动将 ObservableCollection<SomeSpecificNode> 转换为 ObservableCollection<IMyNode>

执行此操作的正确方法是什么?

使用转换器会破坏 NotifyPropertyChange。在我的父 ViewModel 中使用 ObservableCollection<IMyNode> 不适用于同一页面中的其他控件。

谢谢!

这里是一些伪代码:

public class SomeSpecificNode: IMyNode{
}
public interface IMyNode{

}



public class ParentViewModel {
    public ObservableCollection<SomeSpecificNode> SelectedNodes {get;}=> new ObservableCollection<SomeSpecificNode>()

}


<UserControl x:Class="ParentView"
             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" 
             xmlns:local="clr-namespace:ch.VibroMeter.Xms.Configurators.Controls.ActionBar"
             xmlns:dxb="http://schemas.devexpress.com/winfx/2008/xaml/bars"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <UserControl.DataContext>
        <ParentViewModel/>
    </UserControl.DataContext>
    <StackPanel Orientation="Horizontal" Name="RootContainer">
        <SomeChildControl Nodes="{Binding SelectedNodes}" /><!-- This binding will fail !-->
    </StackPanel
</UserControl>



public partial class ParentView : UserControl
{
        public static readonly DependencyProperty NodesProperty = DependencyProperty.Register(
            nameof(Nodes), typeof(ObservableCollection<IMyNode>), typeof(ParentView), new PropertyMetadata(default(ObservableCollection<IMyNode>), OnNodesChanged));

        private static void OnNodesChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            //...
        }

        public  ObservableCollection<IMyNode>  Nodes
        {
            get { return (ObservableCollection<IMyNode>)GetValue(NodesProperty); }
            set { SetValue(NodesProperty, value); }
        }
}

您应该将依赖项 属性 的类型更改为兼容类型,例如 IEnumerable<IMyNode>

您不能将 ObservableCollection<IMyNode> 属性 设置为 ObservableCollection<IMyNode>null 以外的任何值。

一个 ObservableCollection<SomeSpecificNode> 而不是 一个 ObservableCollection<IMyNode> 但它是一个 IEnumerable<IMyNode> 假设 SomeSpecificNode 实现了 IMyNode.

所以编译得很好;

IEnumerable<IMyNode> collection = new ObservableCollection<SomeSpecificNode>();

但事实并非如此:

ObservableCollection<IMyNode> collection = new ObservableCollection<SomeSpecificNode>(); //Cannot implictly convert type...

区别在于IEnumerable<T>是协变的。详情请参考docs