0

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パスエラー:'SomeProperty'プロパティが'オブジェクト''' ModelObject'(HashCode = 56810243)'に見つかりません。BindingExpression:Path = SomeProperty; DataItem ='ModelObject'(HashCode = 56810243); ターゲット要素は'TextBlock'(Name ='');です。ターゲットプロパティは「テキスト」(タイプ「文字列」)です

参考までに、ViewXAMLの関連セクションは次のようになります。

<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実装と私自身の明示的なバージョンとの違いは何が欠けていますか?

4

3 に答える 3

1

I managed to find a solution to this problem here: WPF databinding to interface and not actual object - casting possible?

Turns out the binding will work if it is defined explicitly against the interface type, instead of implicitly, presumably because ModelObject does not have a SomeProperty, but it does have IMyInterface.SomeProperty ?

So, this works;

<DataGridTextColumn Width="Auto" Header="Some Property" 
       Binding="{Binding Path=(mynamespace:IMyInterface.SomeProperty), Mode=OneWay}" />

Though, it does cause designer warnings, as noted in the referenced question.

于 2012-11-30T01:30:31.193 に答える
1

その理由は、PostSharpが明示的な実装を導入しているため、実際にはパブリックプロパティが導入されていないためだと思います。パブリックプロパティを紹介するには、[IntroduceInterface]アドバイス[IntroduceMember]アドバイスを使用する必要があります。

于 2012-11-30T08:09:36.603 に答える
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}
于 2012-11-30T00:45:08.673 に答える