将WPF控件绑定到模型对象上的动态引入接口

时间:2012-11-29 23:56:36

标签: c# wpf data-binding interface postsharp

我正在使用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实现和我自己的显式版本之间有什么不同?

3 个答案:

答案 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}" />

尽管如此,它确实会引起设计师警告,如引用的问题中所述。