
[英]Binding a collection of data objects in a model to a group of controls in a view (WPF)
[英]Binding WPF controls to dynamically introduced interfaces on model objects
我正在使用PostSharp的[CompositionAspect]功能在我的WPF应用程序中动态地将接口插入模型对象。 但是,似乎WPF无法正确绑定(显示)属性,除非在模型对象上显式实现了相关接口?
使用自定义的CompositionAspect(ComposeObjectAspect),我可以通过在运行时将ModelObject强制转换为引入的接口来直接成功地公开内部IMyInterface对象的属性。
// some interface definition, for sample completeness
public interface IMyInterface
{
public string MyProperty { get; set; }
}
// model object, which does NOT implement IMyInterface directly, though the interface is dynamically introduced by PostSharp
[ComposeObjectAspect(typeof(IMyInterface))]
public class ModelObject
{
private IMyInterface actualDataObject;
}
. . .
public class ViewModel
{
public ObservableCollection<IMyInterface> MyData { get; }
public void LoadData()
{
// concrete IMyInterface dtos are returned here, and put into a VM collection
IList<IMyInterface> myData =
(from IMyInterface o in SomeDataSource.LoadLocalDescriptors()
select new ModelObject(o) as IMyInterface).ToList();
this.MyData = new ObservableCollection<IMyInterface>(myData);
}
}
这一切都很好,并且,如果我检查myData列表中的任何对象,或将其强制转换为IMyInterface类型(您可以从上面的ModelObject定义类直接实现,您可以看到它),则可以直接从ActualDataObject看到内部属性。 这一切都很好。
现在,当我尝试将ViewModel.Data集合绑定到WPF数据网格时,出现了一系列绑定错误,例如;
System.Windows.Data错误:40:BindingExpression路径错误:在'object''ModelObject'(HashCode = 56810243)'上找不到'SomeProperty'属性。 BindingExpression:Path = SomeProperty; DataItem ='ModelObject'(HashCode = 56810243); 目标元素是'TextBlock'(Name =''); 目标属性为“文本”(类型为“字符串”)
作为参考,View XAML的相关部分如下所示:
<DataGrid ItemsSource="{Binding MyData}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Width="Auto" Header="Some Property" Binding="{Binding SomeProperty, Mode=OneWay}" />
</DataGrid.Columns>
</DataGrid>
尽管所有数据行均可见(且为空),但网格列显示为空白。
如果我检查“ ModelObject”,则属性IMyInterface.SomeProperty存在。
如果我将IMyInterface直接应用于ModelObject类(并将所有成员作为简单的中继实现到组成的ActualDataObject实例),则绑定就可以了,并且SomeProperty会显示无错误。
我遗漏的是IMyInterface的PostSharp实现和我自己的显式版本之间的不同吗?
我认为原因是PostSharp引入了显式实现,因此实际上没有引入公共属性。 您应该使用[IntroduceInterface]建议和 [IntroduceMember]建议来介绍公共属性。
可能的解决方案:
<DataGrid DataContext="{Binding Data}" ItemsSource="{Binding}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Width="Auto" Header="Some Property" Binding="{Binding SomeProperty, Mode=OneWay}" />
</DataGrid.Columns>
</DataGrid>
要么
<DataGridTextColumn Width="Auto" Header="Some Property" Binding="{Binding Path=actualDataObject.SomeProperty, Mode=OneWay}
我设法在这里找到解决此问题的方法: WPF数据绑定到接口而不是实际的对象-可能进行铸造吗?
事实证明,如果绑定是针对接口类型显式定义的,而不是隐式定义的,则绑定将起作用,大概是因为ModelObject没有SomeProperty,但是它确实具有IMyInterface.SomeProperty吗?
因此,这有效;
<DataGridTextColumn Width="Auto" Header="Some Property"
Binding="{Binding Path=(mynamespace:IMyInterface.SomeProperty), Mode=OneWay}" />
但是,确实会引起设计者警告,如所参考问题中所述。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.