C# 如何更改文本块';如果字符串值不相等,则为背景色?

C# 如何更改文本块';如果字符串值不相等,则为背景色?,c#,wpf,binding,C#,Wpf,Binding,我有一个UserControl,它只存在两个文本块: <UserControl [...] x:Name="root"> <StackPanel Orientation="Vertical"> <TextBlock Text="{Binding Text1, ElementName=root}" /> <TextBlock Text="{Binding Text2, ElementName=root}" />

我有一个UserControl,它只存在两个文本块:

<UserControl [...] x:Name="root">
    <StackPanel Orientation="Vertical">
        <TextBlock Text="{Binding Text1, ElementName=root}" /> 
        <TextBlock Text="{Binding Text2, ElementName=root}" />
    </StackPanel> 
</UserControl>
这就是我在MainWindow.xml中使用这个用户控件的方式:

<local:CmpText Text1="{Binding Password1}" Text2="{Binding Password2}" />
并将第二个文本块的样式设置为

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

但是,即使Text1和Text2属性不匹配,IsEqual始终被证明为“true”(并且TextBlock的背景始终为红色)。我认为我的助手属性“IsEqual”比较了Text1和Text2的默认值,它们恰好为NULL(我没有任何方法来确认这一点,因为我无法调试GUI)。因此,IsEqual的计算似乎发生在我的文本属性被赋值之前。我希望在指定文本属性后进行计算

我不知道如何继续。您能帮忙吗?

您可以在
`WPF
中调试UI,即使它不像usula
.NET
应用程序那样直接。在绑定中,仅出于调试目的,添加一个
转换器
。 还有其他方法可以了解
绑定的情况

看看乔希·史密斯的优秀文章

使用此选项,请查看:

  • 如果您的
    Text1
    Text2
    属性实际上是通过您分配给它们的值获得的
  • 如果有“是/否”,则在某些情况下可能不会发生:例如,您需要按
    TAB
    以松开焦点,因此请运行绑定 至少检查一下这一点,你应该已经能够提出一些想法了

    希望这有帮助。

    您可以在
    `WPF
    中调试UI,即使它不像usula
    .NET
    应用程序那样直接。在绑定中,仅出于调试目的,添加一个
    转换器
    。 还有其他方法可以了解
    绑定的情况

    看看乔希·史密斯的优秀文章

    使用此选项,请查看:

  • 如果您的
    Text1
    Text2
    属性实际上是通过您分配给它们的值获得的
  • 如果有“是/否”,则在某些情况下可能不会发生:例如,您需要按
    TAB
    以松开焦点,因此请运行绑定 至少检查一下这一点,你应该已经能够提出一些想法了


    希望这有帮助。

    目前,WPF无法发现
    IsEqual
    已更改,因此不会重新评估绑定

    你可以做三件事:

  • 使
    IsEqual
    成为另一个依赖项属性,并将s添加到
    Text1
    Text2
    中,每当它们发生更改时,都会更新
    IsEqual

  • 或者,在
    Text1
    Text2
    PropertyChangedCallbacks中为
    IsEqual
    执行并引发PropertyChanged事件

  • 或者,将a与a结合使用,将后台属性直接绑定到
    Text1
    Text2
    。转换器将获得两个字符串作为输入,并返回一个笔刷


  • 目前,WPF无法发现
    IsEqual
    已更改,因此不会重新评估绑定

    你可以做三件事:

  • 使
    IsEqual
    成为另一个依赖项属性,并将s添加到
    Text1
    Text2
    中,每当它们发生更改时,都会更新
    IsEqual

  • 或者,在
    Text1
    Text2
    PropertyChangedCallbacks中为
    IsEqual
    执行并引发PropertyChanged事件

  • 或者,将a与a结合使用,将后台属性直接绑定到
    Text1
    Text2
    。转换器将获得两个字符串作为输入,并返回一个笔刷


  • 首先,确保用作DataContext的对象(具有Password1和Password2属性)实现属性的
    INotifyPropertyChanged
    接口

    要实现这种行为,可以使用:当UserControl的Text1或Text2属性发生更改时,需要强制(重新计算)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);
        }
    }
    

    希望有帮助。

    首先,确保用作DataContext的对象(具有Password1和Password2属性)实现属性的
    INotifyPropertyChanged
    接口

    要实现这种行为,可以使用:当UserControl的Text1或Text2属性发生更改时,需要强制(重新计算)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);
        }
    }
    

    希望有帮助。

    是的,这似乎是最简单的解决方案。此外,#1必须是只读依赖属性。首先,非常感谢。我有一个关于解决方案2的问题。我假设您说应该是UserControl本身实现INotifyPropertyChanged(我不确定其他任何东西是否有意义)。然而,就我所见,“Text1”和“Text2”的PropertyChangedCallbacks是静态的。。。静态PropertyChangedCallback(注册DependencyProperty时传递给PropertyMetadata的调用)如何引发非静态INotifyPropertyChanged.PropertyChanged事件?如果查看PropertyChangedCallback的签名,您将看到它获得一个
    DependencyObject
    作为第一个参数。这是您的用户控件,如果您实现该接口,可以将其强制转换为
    INotifyPropertyChanged
    。我明白了。我确实阅读了文档,但误解了该参数的含义。再次感谢您的澄清!是的,这似乎是最简单的解决方案。此外,#1必须是只读依赖属性。首先,非常感谢。我有一个关于解决方案2的问题。我假设您说应该实现INotifyPropertyChanged的是UserControl本身(我不确定其他任何东西是否会使它更合理)
    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);
        }
    }