【问题标题】:TextBox BorderBrush is not updating after text is changed文本更改后,TextBox BorderBrush 不更新
【发布时间】:2017-03-18 11:19:53
【问题描述】:

我有带有默认 BorderBrush 的 WPF 文本框。当 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 上,然后一切正常。

【问题讨论】:

  • 问题是,默认情况下,WPF 在文本框获得焦点时会在文本框周围添加一个蓝色边框。您应该尝试寻找去除该边框的方法。试试这个链接:(stackoverflow.com/questions/6404059/…)
  • 如果您将绑定模式更改为PropertyChanged 而不是默认的LostFocus 是否有效? Text="{Binding Path=Description, Mode=PropertyChanged}"
  • 这里不要使用转换器,使用StyleDataTrigger

标签: c# wpf binding textbox converter


【解决方案1】:

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

下面是后者在您的视图模型上的可能实现,基于在每次属性更改后执行的 Validate 方法,以及作为每个属性错误存储的 Dictionary&lt;string, List&lt;string&gt;&gt;

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}" />

【讨论】:

    【解决方案2】:

    你可以试试这个,给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>
    

    【讨论】:

      猜你喜欢
      • 2013-06-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-23
      • 2015-11-11
      • 1970-01-01
      • 1970-01-01
      • 2010-10-11
      相关资源
      最近更新 更多