2012-02-10 4 views
2

私は2つだけのTextBlockの存在のUserControlを持っている:文字列の値が等しくない場合、TextBlockの背景色を変更するにはどうすればよいですか?

<UserControl [...] x:Name="root"> 
    <StackPanel Orientation="Vertical"> 
     <TextBlock Text="{Binding Text1, ElementName=root}" /> 
     <TextBlock Text="{Binding Text2, ElementName=root}" /> 
    </StackPanel> 
</UserControl> 

対応ビハインドコードは次のようになります。

public static readonly DependencyProperty Text1Property = DependencyProperty.Register("Text1", typeof(String), typeof(CmpText)); 
public static readonly DependencyProperty Text2Property = DependencyProperty.Register("Text2", typeof(String), typeof(CmpText)); 

public string Text1 
{ 
    get { return (string)GetValue(Text1Property); } 
    set { SetValue(Text1Property, value); } 
} 

public string Text2 
{ 
    get { return (string)GetValue(Text2Property); } 
    set { SetValue(Text2Property, value); } 
} 

そして、これは私がMainWindow.xmlでこのユーザーコントロールを使用する方法です。

Text1とText2の両方が不一致の場合、2番目のTextBlockの背景色が赤に変更されます。

私はコードビハインドでヘルパープロパティを使用しようとしました:

public bool IsEqual { get { return Text1 == Text2; } } 

そして

<Style TargetType="{x:Type TextBlock}"> 
    <Style.Triggers> 
     <DataTrigger Binding="{Binding IsEqual, ElementName=root}" Value="True"> 
      <Setter Property="Background" Value="Red"/> 
     </DataTrigger> 
    </Style.Triggers> 
</Style> 

に2つ目のTextBlockのスタイルを設定するしかし、ISEQUALは常に(「真」であることが判明しましたText1 & Text2のプロパティが一致しない場合でも、TextBlockの背景は常に赤です)。私のヘルパープロパティ 'IsEqual'は、Text1 & Text2のデフォルト値をNULLと比較していると思います(私はGUIをデバッグできないので、それを確認する方法はありません)。したがって、IsEqualの評価は、テキストプロパティの値が割り当てられる前に発生するようです。の後に、評価が割り当てられるように、を入力します。

私は進行方法がわかりません。手伝ってくれますか?

答えて

4

現在、WPFがIsEqualが変更されたことを知ることができないため、バインディングは再評価されません。彼らは変更するたびに、IsEqualを更新し、

  1. IsEqual別の依存関係プロパティ作り、Text1Text2PropertyChangedCallback秒を追加します。

    あなたは3つのことを行うことができます。

  2. または、INotifyPropertyChangedを実装し、Text1Text2 PropertyChangedCallbacksでIsEqualためにPropertyChangedイベントを発生させます。

  3. あるいは、Text1Text2に直接BackgroundプロパティをバインドするIMultiValueConverterと一緒にMultiBindingを使用しています。コンバータは2つの文字列を入力として取得し、ブラシを返します。

+0

+1私の優先オプションは#2になりますが – Rachel

+0

はい、最も簡単な解決策です。さらに、#1は読み取り専用の依存関係プロパティでなければなりません。 – Clemens

+0

まずは、ありがとうございます。私は解決策#2について質問があります。私はそれがINotifyPropertyChangedを実装する必要があるUserControl自体だと仮定していると仮定します。しかし、私が見る限り、 'Text1'と 'Text2'のPropertyChangedCallbacksは静的なものです...静的PropertyChangedCallback(DependencyPropertyの登録時にPropertyMetadataに渡すもの)は、非静的INotifyPropertyChanged.PropertyChangedイベント? – user1202727

0

デバッグUIが`WPFであっても、それはわかりやすくない場合でも、.NETアプリケーションです。あなたのバインディングでは、デバッグのためだけにConverterを追加します。 bindingで何が起こっているのかを説明する他の方法もあります。

チェックアウトTips on how to debug and learn about WPF優秀なジョシュ・スミスの記事。これを使用する

、チェックアウト:

  1. をごText1Text2プロパティは、あなたがそれらに割り当てられた値で、実際に取得した場合。
  2. はい/いいえの場合は、何も起こらない場合があります。たとえば、フォーカスを失うためにTABを押す必要があるため、バインディングを実行します。

少なくともこれを確認すると、にはには既にいくつかのアイデアが出てくるはずです。

これが役に立ちます。

0

まず、(パスワード及びPassword2という特性を有する)のDataContextとして使用されるオブジェクトは、プロパティのINotifyPropertyChangedインタフェースを実装することを確認します。ユーザーコントロールのテキスト1 またはテキスト2プロパティが変更されたとき、強制する必要がある(再計算)ISEQUALプロパティ:

は、あなたが Dependency Property Callbacks and Validationを使用することができ、そのような動作を実装するには。ここで

は実装です:

public partial class CmpTextView : UserControl 
{ 
    public CmpTextView() 
    { 
     InitializeComponent(); 
    } 

    private static readonly DependencyPropertyKey IsEqualPropertyKey = DependencyProperty.RegisterReadOnly("IsEqual", typeof(bool), typeof(CmpTextView), new FrameworkPropertyMetadata(null, CoerceIsEqual)); 
    public static readonly DependencyProperty IsEqualProperty = IsEqualPropertyKey.DependencyProperty; 

    public bool IsEqual 
    { 
     get { return (bool)GetValue(IsEqualProperty); } 
    } 

    private static object CoerceIsEqual(DependencyObject d, object baseValue) 
    { 
     CmpTextView cmpTextView = (CmpTextView) d; 
     return cmpTextView.Text1 == cmpTextView.Text2; 
    } 

    public static readonly DependencyProperty Text1Property = DependencyProperty.Register("Text1", typeof(String), typeof(CmpTextView), new FrameworkPropertyMetadata(OnTextChanged)); 

    public string Text1 
    { 
     get { return (string)GetValue(Text1Property); } 
     set { SetValue(Text1Property, value); } 
    } 

    public static readonly DependencyProperty Text2Property = DependencyProperty.Register("Text2", typeof(String), typeof(CmpTextView), new FrameworkPropertyMetadata(OnTextChanged)); 

    public string Text2 
    { 
     get { return (string)GetValue(Text2Property); } 
     set { SetValue(Text2Property, value); } 
    } 

    private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     d.CoerceValue(IsEqualProperty); 
    } 
} 

はそれがお役に立てば幸いです。

+0

ここでは、プロパティの値の強制は少し過度だと思います。 IsEqualを[RegisterReadOnly](http://msdn.microsoft.com/en-us/library/system.windows.dependencyproperty.registerreadonly.aspx)で読み取り専用の依存関係プロパティにしてから、単純に設定するだけで十分ですそれは 'OnTextChanged'です。 – Clemens

+0

@Clemens、 'RegisterReadOnly'を指摘してくれてありがとう!コードを更新しました。 しかし、価値の強制はそのような問題を解決するように設計されているため、価値の強制はここでは過度ではないと私は考えています。明確化とリフレッシュのために、値強制は、依存関係を同期させて有効にしておく(相互に依存する)メカニズムです。 –

+0

私は、値の強制が設計されていることを知っています。私はそれがここでは不要であることも知っています。それは、追加の利益なしに単純なことをより複雑にするでしょう。読み取り専用の依存関係プロパティを強制する必要はありません。 – Clemens

関連する問題