Как изменить цвет фона TextBlock, если значения строк неравны? - PullRequest
2 голосов
/ 10 февраля 2012

У меня есть UserControl, который существует только из двух текстовых блоков:

<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); } 
}

И вот как я использую этот UserControl в MainWindow.xml:

<local:CmpText Text1="{Binding Password1}" Text2="{Binding Password2}" />

Что мне в основном нужно, так это чтобы фон второго TextBlock изменил свой цвет на красный, если и Text1, и Text2 неравны.

Я пытался использовать вспомогательное свойство в коде:

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>

Однако IsEqual всегда оказывается «истиной» (а фон TextBlock всегда красный), даже если свойства Text1 и Text2 не совпадают. Я думаю, что мое вспомогательное свойство 'IsEqual' сравнивает значения по умолчанию Text1 & Text2, которые оказываются NULL (у меня нет никакого способа подтвердить это, так как я не могу отладить GUI). Таким образом, оценка IsEqual, кажется, происходит до того, как моим свойствам текста будут присвоены какие-либо значения. Я хочу, чтобы оценка произошла после свойств текста.

Я не знаю, как поступить. Вы можете помочь?

Ответы [ 3 ]

4 голосов
/ 10 февраля 2012

В настоящее время WPF не может обнаружить, что IsEqual изменился, поэтому привязка не будет переоцениваться.

Вы могли бы сделать три вещи:

  1. Создайте IsEqual другое свойство зависимости и добавьте PropertyChangedCallback s к Text1 и Text2, которые при каждом изменении обновляют IsEqual.

  2. Или реализовать INotifyPropertyChanged и вызвать событие PropertyChanged для IsEqual в Text1 и Text2 PropertyChangedCallbacks.

  3. Или используйте MultiBinding в сочетании с IMultiValueConverter , чтобы связать свойство Background напрямую с Text1 и Text2. Преобразователь получит две строки в качестве входных данных и вернет кисть.

0 голосов
/ 11 февраля 2012

Прежде всего, убедитесь, что объект, используемый как DataContext (со свойствами Password1 и Password2), реализует интерфейс INotifyPropertyChanged для свойств.

Чтобы реализовать такое поведение, вы можете использовать Обратные вызовы и проверки свойств зависимостей : при изменении свойства Text1 или Text2 UserControl необходимо принудительно выполнить (повторно рассчитать) IsEqual свойство.

Вот реализация:

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 голосов
/ 10 февраля 2012

Вы можете отладить пользовательский интерфейс в `WPF, даже если это не так просто, как в обычном .NET приложении. В привязке, только для целей отладки, добавьте, например, Converter. Есть и другие способы выяснить, что происходит с binding.

Ознакомьтесь с Советы по отладке и изучению WPF Отличная статья Джоша Смита.

Используя это, проверьте:

  1. Если ваши свойства Text1 и Text2 фактически получают значения, которые вы им присваиваете.
  2. Если есть да / нет, есть условие, когда этого может не произойти: например, вам нужно нажать TAB, чтобы потерять фокус, поэтому запустите связывание.

Проверяя хотя бы это, вы должны уже быть в состоянии выдвинуть некоторые идеи.

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...