文本更改后,TextBox BorderBrush不会更新

时间:2016-11-04 15:00:36

标签: c# wpf binding textbox converter

我有WPF TextBox,默认使用BorderBrush。当TextBox有空内容时,我想以红色更改BorderBrush。这是我的代码:

<TextBox Width="200" Text="{Binding Path=Description}" Name="tbDescription" Grid.Row="1" Grid.Column="2" Margin="2" 
                             BorderBrush="{Binding RelativeSource={RelativeSource Self},
                             Path=Text,
                             Converter={StaticResource borderBrushColorConverter}}">

这是我的转换器:

public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            string text = value as string;

            if (string.IsNullOrEmpty(text))
                return Brushes.Red;

            return Brushes.Transparent;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }

问题是只有当TextBox焦点丢失时,边框才会变红。我尝试在Background属性上使用相同的代码而不是BorderBrush,然后一切正常。

2 个答案:

答案 0 :(得分:1)

您可以尝试这样做,设置Tempalte

的样式
<TextBox BorderBrush="{Binding RelativeSource={RelativeSource Self},
                         Path=Text,
                         Converter={StaticResource borderBrushColorConverter}}">
        <TextBox.Style>
            <Style  TargetType="{x:Type TextBox}">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type TextBox}">
                            <Border x:Name="Bd" 
                                    SnapsToDevicePixels="true" 
                                    Background="{TemplateBinding Background}" 
                                    BorderBrush="{TemplateBinding BorderBrush }"
                                    BorderThickness="{TemplateBinding BorderThickness}" 
                                    Width="{TemplateBinding Width}" 
                                    Height="{TemplateBinding Height}">
                                <ScrollViewer x:Name="PART_ContentHost"></ScrollViewer>
                            </Border>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </TextBox.Style>
    </TextBox>

答案 1 :(得分:1)

也许您尝试解决的问题不仅仅是条件样式,而是数据验证。如果是这种情况,那么值得考虑在您的视图模型中添加对IDataErrorInfo或更好 - INotifyDataErrorInfo的支持。

下面是视图模型中后者的可能实现,基于在每次属性更改后执行的Validate方法,以及Dictionary<string, List<string>>每属性错误存储:

public class MyViewModel : INotifyPropertyChanged, INotifyDataErrorInfo
{
    public string Description
    {
        get { return _description; }

        set
        {
            _description = value;
            NotifyPropertyChanged();
            Validate();
        }
    }

    private string _description;

    private void Validate()
    {
        Errors[nameof(Description)].Clear();

        if (string.IsNullOrEmpty(Description))
        {
            Errors[nameof(Description)].Add("The text cannot be empty");
        }

        if (Errors[nameof(Description)].Any())
        {
            NotifyErrorsChanged(nameof(Description));
        }
    }

    public IEnumerable GetErrors(string propertyName)
        => Errors.ContainsKey(propertyName) ? Errors[propertyName] : Enumerable.Empty<string>();

    public bool HasErrors
        => Errors.Any(propertyErrors => (propertyErrors.Value ?? Enumerable.Empty<string>()).Any());

    public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;

    protected virtual void NotifyErrorsChanged([CallerMemberName] string propertyName = null)
        => ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(propertyName));

    private IDictionary<string, List<string>> Errors { get; }
        = new Dictionary<string, List<string>>
        {
            {nameof(Description), new List<string>()}
        };

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
        => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

视图侧缩小为:

<TextBox Text="{Binding Description, Mode=TwoWay, ValidatesOnNotifyDataErrors=True, UpdateSourceTrigger=PropertyChanged}" />