如何将子类型的集合绑定到依赖项 属性
How to bind a collection of a subtype to a dependency property
我正在 WPF 中创建一个 UserControl,它可以用于 IMyNode
类型的任何对象。基本上,它通过依赖项 属性 接收 ObservableCollection,向其注册并执行一些操作。
在我的一个用例中,我在一个使用(并且需要)SomeSpecificNode
的 ObservableCollection 的控件中使用。 SomeSpecificNode
是 IMyNode
.
的实现
目前,我有一个绑定错误:
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。
我正在 WPF 中创建一个 UserControl,它可以用于 IMyNode
类型的任何对象。基本上,它通过依赖项 属性 接收 ObservableCollection,向其注册并执行一些操作。
在我的一个用例中,我在一个使用(并且需要)SomeSpecificNode
的 ObservableCollection 的控件中使用。 SomeSpecificNode
是 IMyNode
.
目前,我有一个绑定错误:
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。