web-dev-qa-db-ja.com

コードビハインドでクラスメンバーにWPFバインド

かなり単純な質問ですが、ここで完全な答えを見つけることができないようです...

分離コードでクラスメンバーのプロパティにxamlでデータバインドする必要があります。

<Window x:Class="Main">
    <customcontrol Name="View" IsChecked="{Binding ElementName=RecordProp, Path=IsViewChecked}" />
...

背後のコードは次のようになります。

class Main 
{    
    ...
    private Record _record;
    public Record RecordProp
    {
      get { return _record; }
    }
    ...
}


class Record
{
  public bool IsViewChecked
  {
    get; set;
  }
}

私が今持っているものは機能しません、何が間違っていますか?

30
jaws

パスには、ソース(DataSource、DataContext、RelativeSource、ElementName)を使用する必要があります。 ElementNameは、XAMLでx:Nameによって宣言された要素を参照するためにのみ使用できます。代わりにこれを試して、ソースとしてウィンドウを指定します。

IsChecked="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}, Path=RecordProp.IsViewChecked}"
27
John Bowen

ここで私が見ているのは、ウィンドウのクラス名がMainであり、それにRecordPropプロパティが追加されており、IsCheckedという名前の要素のRecordPropプロパティにバインドしようとしていることです。名前の仕組みについて少し混乱していると思います。

x:Name属性をXAML要素に追加すると、ウィンドウクラスにその名前のフィールドが作成されます。これにより、コード内の名前付き要素を参照できるようになり、おそらくバインディングでも同じことができると考えるようになりました。

しかし、バインディングは名前付き要素を見つける方法ではありません。 x:Name属性alsoは、XAML要素が作成したオブジェクトを取得し、ウィンドウのネームスコープでその名前の下に登録します。 (XAML名前スコープに関する MSDNの記事を参照してください。 )これは、バインディングが要素名を解決するために参照するものです。オブジェクトをnamescopeに追加することはないので、バインディングでElementNameプロパティを設定しても、オブジェクトは見つかりません。

考えられることはいくつかあります。ウィンドウのプロパティに本当にバインドしたい場合は、ウィンドウに名前を付け、プロパティパスを使用してプロパティにバインドできます。

<Window x:Name="MainWindow" x:Class="Main">
...
   <customcontrol Name="View" IsChecked="
                 {Binding ElementName=MainWindow, 
                  Path=RecordProp.IsViewChecked}" />

さらに簡単なのは、コンストラクタでデータコンテキストを設定することです。

DataContext = this;

これを行ったら、次のようにRecordPropプロパティ(およびウィンドウの他のプロパティ)にバインドできます。

<customControl Name="View" IsChecked={Binding RecordProp.IsChecked}/>

もちろん、ウィンドウのデータコンテキストを他の何かに設定する必要がある場合は機能しません。

別の可能性は、このようなプロパティを実装することです:

public Record RecordProp 
{
  get { return (Record)Resources["RecordProp"]; }
  set { Resources["RecordProp"] = value; }
}

これに(たとえば)Binding {DynamicResource RecordProp}, Path=IsChecked"を使用してバインドできます。これは動的リソースであるため、ウィンドウの外部の何かがウィンドウのRecordPropプロパティを設定すると、そのバインディングが更新されます。これは、RecordPropをプロパティにしただけでは発生しません(変更通知を実装しない限り)。

30
Robert Rossney

これまでに述べた答えよりも簡単な答えがあると思います。これをXAMLのウィンドウ宣言(最初のタグ)に追加するだけです。

x:Name="this"

次に、次のようにデータバインドできます。

<customcontrol Name="View" IsChecked="{Binding ElementName=this, Path=RecordProp.IsViewChecked}" />

C#が「this」がすでに存在することについて不平を言っているかどうかを確認したところ、そうではなかったと思います。どちらもまったく同じオブジェクトを参照しているためです。

これは、私が同じ問題に遭遇したときに使用したソリューションであり、非常に直感的に使用できることがわかりました。

7
JoeCool

データバインディングはプライベートフィールドに対して機能しません。代わりにパブリックプロパティを対象としています。値_recordを公開し、代わりにバインドしてみてください。

リファレンス- http://msdn.Microsoft.com/en-us/library/ms743643.aspx

3
JaredPar