我正在使用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:路径= SomeProperty; DataItem ='ModelObject'(HashCode = 56810243); target元素是'TextBlock'(Name =''); target属性是'Text'(类型'String')
作为参考,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实现和我自己的显式版本之间有什么不同?
答案 0 :(得分:1)
我认为原因是PostSharp引入了一个显式实现,所以实际上没有引入公共属性。您应该使用[IntroduceInterface]建议和 [IntroduceMember]建议来介绍公共属性。
答案 1 :(得分:0)
可能的解决方案:
<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}
答案 2 :(得分:0)
我设法在这里找到了解决这个问题的方法:WPF databinding to interface and not actual object - casting possible?
如果绑定是针对接口类型显式定义的,而不是隐式的,大概是因为ModelObject没有SomeProperty,但它确实有IMyInterface.SomeProperty?
所以,这有效;
<DataGridTextColumn Width="Auto" Header="Some Property"
Binding="{Binding Path=(mynamespace:IMyInterface.SomeProperty), Mode=OneWay}" />
尽管如此,它确实会引起设计师警告,如引用的问题中所述。