私はこのようなものを使用したいUserControl
を作成しています:
<controls:ColorWithText Color="Red" Text="Red color" />
これまでのところ、次のような同様のコントロールを実装しました。
<UserControl x:Class="Namespace.ColorWithText" Name="ThisControl">
<StackPanel Orientation="Horizontal" >
<Border Width="15" Height="15" Background="{Binding Color, ElementName=ThisControl}" />
<TextBlock Text="{Binding Text, ElementName=ThisControl}" />
</StackPanel>
</UserControl>
Color
およびText
は、コードで定義されたコントロールの依存関係プロパティです。これは機能しますが、毎回ElementName
を指定する必要はありません。
動作する別のオプションは
<UserControl x:Class=… DataContext="{Binding ElementName=ThisControl}" Name="ThisControl">
ElementName
sを指定していませんが、それも私にとってはきれいな解決策ではないようです。
2つの質問があります。
<UserControl DataContext="{RelativeSource Self}">
仕事?最初に、試してください:
<UserControl DataContext="{Binding RelativeSource={RelativeSource Self}}">
2番目の質問では、ElementName
またはAncestorBinding
を使用することが、UserControl
のプロパティにバインドする最適な方法だと思います。
<UserControl DataContext="{RelativeSource Self}">
?これは、コントロールを使用する方法です
<Grid DataContext="{StaticResource ViewModel}">
<!-- Here we'd expect this control to be bound to -->
<!-- ColorToUse on our ViewModel resource -->
<controls:ColorWithText Color="{Binding ColorToUse}" />
</Grid>
コントロールでデータコンテキストをハードコーディングしているため、ViewModelではなく、ColorWithTextオブジェクトでColorToUseプロパティをルックアップしようとします。失敗します。
これが、ユーザーコントロールでDataContextを設定できない理由です。 Brandur に感謝します。
代わりに、コントロールの最初の子UI要素でDataContextを設定する必要があります。
あなたの場合はあなたが欲しい
<StackPanel
DataContext="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}"
Orientation="Horizontal" >
コントロールを参照するDataContextができたので、相対バインディングを使用してそのコントロールのプロパティにアクセスできます。
あなたが使用する必要があります
{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=Color}
データバインディングに関連する疑問については、常にこのシートを参照してください。
http://www.nbdtech.com/Blog/archive/2009/02/02/wpf-xaml-data-binding-cheat-sheet.aspx
私はこれが回答されたことを知っていますが、どの説明もDataContextとその仕組みの理解を与えません。このリンクはそのために素晴らしい仕事をします。
WPF、SILVERLIGHT、およびWP7(パート2)でのデータバインドについて知りたいすべてのこと
あなたの質問#1に答えて
なぜ<UserControl DataContext="{RelativeSource Self}">
仕事?
これは上記のリンクの要約です。 DataContextは、UserControl ElementレベルでSelfに設定しないでください。これは、DataContextの継承を破壊するためです。 selfに設定し、このコントロールをWindowまたは別のコントロールに配置すると、Windows DataContextを継承しません。
DataContextは、どこかで上書きされない限り、XAMLのすべての下位要素とUserControlのすべてのXAMLに継承されます。 UserControl DataContextをそれ自体に設定すると、DataContextが上書きされ、継承が中断されます。代わりに、XAMLの1つの要素、場合によってはStackPanelにネストします。ここにDataContextバインディングを配置し、UserControlにバインドします。これにより、継承が保持されます。
この詳細な説明については、以下のリンクも参照してください。
WPF/SILVERLIGHTで再利用可能なユーザーコントロールを作成するための簡単なパターン
あなたの質問#2に答えて
このようなことをする最良の方法は何ですか?
以下のコード例を参照してください。
<UserControl x:Class="Namespace.ColorWithText" Name="ThisControl">
<StackPanel Orientation="Horizontal" DataContext={Binding ElementName=ThisControl}>
<Border Width="15" Height="15" Background="{Binding Color" />
<TextBlock Text="{Binding Text}" />
</StackPanel>
これを行うと、各バインディングでElementNameが不要になることに注意してください。
コンストラクタ自体でdatacontextをselfに設定できます。
public ColorWithText()
{
InitializeComponent();
DataContext = this;
}
今、あなたは単に言うことができます
<UserControl x:Class="Namespace.ColorWithText" Name="ThisControl">
<StackPanel Orientation="Horizontal" >
<Border Width="15" Height="15" Background="{Binding Color}" />
<TextBlock Text="{Binding Text}" />
</StackPanel>
</UserControl>