如果Text值已更改,则更改自定义TextBox的背景属性

时间:2017-08-28 11:29:52

标签: wpf xaml binding dependency-properties ivalueconverter

我有一个自定义TextBox控件,它继承System.Windows.Controls.TextBox并实现INotifyPropertyChanged接口。

public partial class V3TextBox : TextBox, INotifyPropertyChanged

它具有自定义OriginalValue属性,并且覆盖了基础Text属性。

我想象它的工作方式是将TextOriginalValue绑定到两个不同的字符串属性,并将其Background设置为黄色,如果这两个字符串是如果它们再次变得相同,那就不一样了又回到白色。

这些是我的TextPropertyChanged属性:

private Binding PropertyChangedBinding = new Binding()
{
    Path = new PropertyPath("ChangedPropertyBackground")
};

public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string name)
{
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}

private string text { get; set; } = "";
public new string Text
{
    get
    {
        return text;
    }
    set
    {
        text = value;
        if (value == originalValue)
            BindingOperations.ClearBinding(this, BackgroundProperty);
        else
            SetBinding(BackgroundProperty, PropertyChangedBinding);
        OnPropertyChanged("Background");
    }
}

现在,问题可能在于为DependencyProperty属性设置OriginalValue

他们看起来像这样:

private string originalValue;
public string OriginalValue
{
    get
    {
        return (string)GetValue(TestProperty);
    }
    set
    {
        originalValue = value;
        SetValue(TestProperty, value);
    }
}

public static readonly DependencyProperty TestProperty =
    DependencyProperty.Register("OriginalValue", typeof(string),
    typeof(V3TextBox), new FrameworkPropertyMetadata(default(string)));

private void OnTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    SetValue(TestProperty, e.NewValue);
}

XAML中的控件使用情况如下所示:

<Ctrls:V3TextBox x:Name="txtBxDiscountNote"
    Text="{Binding EditedNote, Mode=TwoWay, NotifyOnTargetUpdated=True}"
    OriginalValue="{Binding OriginalNote, Mode=TwoWay}"/>

DataContext已在XAML中设置。

问题是OriginalValue属性永远不会更改,它总是null并且只有在以编程方式更改Background属性时才会触发更改Text的代码,不通过GUI输入。使用IValueConverter更容易实现吗?单个表格上将有大约30个这些控件。

2 个答案:

答案 0 :(得分:0)

这样的事情应该有效:

public class V3TextBox : TextBox
{
    public static readonly DependencyProperty OriginalValueProperty =
        DependencyProperty.Register("OriginalValue", typeof(string),  typeof(V3TextBox));

    public static readonly DependencyProperty ChangedBackgroundProperty =
        DependencyProperty.Register("ChangedBackground", typeof(Brush), typeof(V3TextBox));

    public string OriginalValue
    {
        get { return (string)GetValue(OriginalValueProperty); }
        set { SetValue(OriginalValueProperty, value); }
    }

    public Brush ChangedBackground
    {
        get { return (Brush)GetValue(ChangedBackgroundProperty); }
        set { SetValue(ChangedBackgroundProperty, value); }
    }

    protected override void OnTextChanged(TextChangedEventArgs e)
    {
        base.OnTextChanged(e);

        if (Text == OriginalValue)
        {
            ClearValue(BackgroundProperty);
        }
        else
        {
            Background = ChangedBackground;
        }
    }
}

像这样使用:

<local:V3TextBox OriginalValue="Hello" ChangedBackground="Yellow"/>

答案 1 :(得分:0)

这是我目前的代码:

public partial class V3TextBox : TextBox
{
    public static readonly DependencyProperty OriginalValueProperty =
        DependencyProperty.Register("OriginalValue", typeof(string), typeof(V3TextBox));
    public string OriginalValue
    {
        get
        {
            return (string)GetValue(OriginalValueProperty);
        }
        set
        {
            SetValue(OriginalValueProperty, value);
        }
    }

    protected override void OnTextChanged(TextChangedEventArgs e)
    {
        base.OnTextChanged(e);

        if (Text == OriginalValue)
            SetResourceReference(BackgroundProperty, "V3CtrlDefaultBackground");
        else
            SetResourceReference(BackgroundProperty, "V3CtrlChangedBackground");
    }


    public V3TextBox()
    {
        InitializeComponent();
    }
}

我正在使用它:

<Ctrls:V3TextBox x:Name="txtBxLocID"
    OriginalValue="{Binding LocationID, Mode=OneTime}"
    Text="{Binding LocationID, Mode=TwoWay}"/>

这意味着,我将TextOriginalValue绑定到同一个属性,但后者设置了Mode=OneTime

所以OriginalValue只被设置一次,并且只要它存活就保持其值,并且我能够将它与当前的Text值进行比较。

@Clemens我正在使用你的一些代码,所以它会被标记为正确答案,请告诉我你是否对我的代码有任何建议?我需要在XAML中使用您的代码再设置一个属性,这样我就不会将DependencyProperty用于Background Brush。也许如果有办法在Text中设置XAML属性,请在代码中首次将其设置为OriginalValue,然后将其进行比较以获得进一步的更改?后面的代码可以以某种方式知道第一次调用事实绑定或类似的事情吗?如果XAML可以在没有OriginalValue属性的情况下编写,那将会很好。在OriginalValue本身的XAML中看不到V3TextBox,只需One-way将其绑定到Text也可以。