4

私はMVVMパターンを使用しているので、自分のコントロールにはViewとViewModelが含まれています。
ViewModelは、ViewbyDataContextプロパティに接続されています。これにより、バインディングに問題が発生します。なんで?

この状況を想定します。
新しいユーザーコントロールを作成しました。たとえば、「SuperTextBox」です。プロパティ「SuperValue」があります。
そして今、私はそのようなことをします:

<Window>
    <Window.DataContext>
        <vm:WindowViewModel/>
    </Window.DataContext>

    <local:SuperTextBox SuperValue="{Binding Test}"/>
</Window>

「バインディングプロセス」はSuperTextBox.SuperValueをWindow.DataContext.Testと結合すると思いましたが、「バインディングプロセス」はSuperTextBox.SuperValueとSuperTextBox.DataContext.Testを結合します。私にとって不自然で誤解を招くものです。

「TextBox」のような他のコントロールは、DataContextがないため、上記の方法で使用できます。

MVVMパターンを使用して、(親コントロールのDataContextへの)自然なバインディングを維持するUserControlを作成するにはどうすればよいですか?

編集:

私は親にどのように拘束するかについて多くの答えを得ました、しかし私はこれを以前に知っています。問題は、MVVMパターン(ViewModelを持つ)を介してUserControlを作成し、自然なバインディングを維持するにはどうすればよいかということです。デフォルトでは、親のDataContextになります。

ViewMoldelが欲しいのですが、それでも次のようにバインドできます。

<local:SuperTextBox SuperValue="{Binding Test}"/>

出来ますか?

4

4 に答える 4

3

に適用されるすべてのバインディングcontrol always first look for the binding in its DataContext。DataContextがコントロールに設定されていない場合、DataContextが見つからwalks up the Visual Treeない限り、親までです。

DataContexttextBoxのをWindowのDatContextとは異なる値に設定した場合でも、は常に、ではTestなく、その特定のDataContextのプロパティを検索しますWindow's DataContext

<TextBox>
   <TextBox.DataContext>
      <vm:ViewModelForTextBox/>
   </TextBox.DataContext>
   <TextBox.Text>
      <Binding Path="Test"/>
   </TextBox.Text>
</TextBox>

これで、xamlはクラスではなくTestクラスでプロパティを検索し、プロパティがクラスで見つからない場合は、WindowのDataContextクラスを検索しません。ViewModelForTextBoxWindowViewModelTestViewModelForTextBoxbinding will fail silently

カスタムUserControlのDataContextを設定したいが、親の(ウィンドウ)dataContextにバインドしたい場合は、次のRelativeSource MarkupExtensionようにバインディングでを使用する必要があります-

<local:SuperTextBox SuperValue="{Binding Path=DataContext.Test,
                                RelativeSource={RelativeSource Mode=FindAncestor,
                                                 AncestorType={x:Type Window}}}">

詳細については、MSDNの記事を参照してください

于 2012-10-21T07:42:25.753 に答える
2

エラーがあるため、SuperTextBoxコードを投稿する必要があります。

通常、依存関係プロパティ(この場合は「SuperValue」)を使用してユーザーコントロールを作成しますが、最も重要なことは、SuperTextBoxのデータコンテキストをそれ自体に設定しないことです。

「SuperValue」にバインドするには、SuperTextBox内でelementnameバインディングを使用する必要があります

 <SuperTextBox x:Name="uc">
   <TextBox Text="{Binding ElementName=uc, Path=SuperValue}/>
 </superTextBox>

あなたがそのようにこれをするなら-あなたの

 <local:SuperTextBox SuperValue="{Binding Test}"/>

動作し、vm:WindowViewModelのテストプロパティにバインドする必要があります。それが上記のようにバインディングを書く唯一の方法です。

編集:ユーザーコントロール用のビューモデルを作成したい場合は、SuperTextViewmodelとしましょう。次に、プロパティ「SuperValue」があります。現在、データコンテキストを2回設定することはできないため、SuperTextViewmodelタイプのWindowViewmodelにプロパティを追加し、必要に応じてプロパティを処理する必要があることをお勧めします。

あなたのバインディングはこのように見えます

 <local:SuperTextBox DataContext="{Binding MySuperTextViewmodelInstanceOnWindowViewmodel}"/>

私は答えの最初の部分に行きます:)私はいつもビューにはビューモデルが必要だと言いますが、ユーザーコントロールの依存関係のプロパティです。

于 2012-10-21T08:37:12.873 に答える
1

私は自分の質問に奇妙に答えているように感じますが...
私自身のコントロールで私はそのようなことをしました:

<UserControl>
    <Grid>
        <Grid.DataContext>
             <vm:UserControlViewModel />
        </Grid.DataContext>
        // here realy code of control
    </Grid>
</UserControl>

これで、制御外および制御内で「自然な」バインディングを使用できます。:)

于 2012-11-03T02:13:37.947 に答える
1

ウィンドウの祖先のデータコンテキストを「検索」する必要があります。バインディングは次のようになります。

<local:SuperTextBox SuperValue="{Binding Path=DataContext.Test, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}">
于 2012-10-21T02:01:17.243 に答える