WPF-在ItemsControl中以编程方式创建控件验证

本文关键字:方式 创建 控件 验证 编程 ItemsControl WPF- | 更新日期: 2023-09-27 18:28:14

我正在努力解决WPF代码中的奇怪问题。我有一个组合框,它允许用户选择其中一个选项。这个组合框中的每个项目都是某种string.Format()模式。例如,当用户选择选项'Hello {0} world'时,我的代码生成两个TextBlocks,其中'Hello''world',以及它们之间的一个TextBox,用户可以在其中提供他的输入。

这是我的xaml:

<ComboBox ItemsSource="{Binding PossiblePatternOptions}" DisplayMemberPath="Pattern" SelectedItem="{Binding SelectedPattern, ValidatesOnDataErrors=True}" Width="250" Margin="5,0,25,0"/>
<ItemsControl ItemsSource="{Binding SelectedPattern.GeneratedControls}"/>

SelectedPattern.GeneratedControlsObservableCollection<UIElement>:

public ObservableCollection<UIElement> GeneratedControls
{
   get
   {
      return _generatedControls ?? (_generateControls = new ObservableCollection<UIElement>(GenerateControls(_splittedPattern)));
   }
}

以下是我如何创建新的TextBox(在GenerateControls方法中):

var placeholderChunk = chunk as TextBoxPlaceholder;
var textBox = new TextBox();
textBox.ToolTip = placeholderChunk.Description;
Binding binding = new Binding("Value");
binding.ValidatesOnDataErrors = true;
binding.Source = placeholderChunk;
binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
textBox.SetBinding(TextBox.TextProperty, binding);

TextBoxPlaceholder实现IDataErrorInfo,并为错误输入提供错误详细信息:

public class TextBoxPlaceholder : IDataErrorInfo
{
   public string Value {get;set;}
   public string this[string columnName]
   {
      get
      {
         switch (columnName)
         {
            case "Value":
            return string.IsNullOrEmpty(Value) ? "Error" : string.Empty;
            default:
            return string.Empty;
         }
      }
    }
   public string Error
   {
      get { throw new NotImplementedException(); }
   }
}

问题是,当我第一次从组合框中选择一个选项时,生成的TextBoxes会被正确验证,它们周围会有漂亮的红色边框,但当我选择之前选择的选项时,不会发生验证,也不再有红色边框。我注意到,当我更改GeneratedControls属性中的代码,使其每次都重新创建集合时,它工作正常。这里可能有什么问题?

我知道这可能解释得很糟糕,如果有任何误解,我会澄清的。

WPF-在ItemsControl中以编程方式创建控件验证

您的"Value"属性在更改时似乎不会触发更新,因此文本框的文本绑定无法对更改做出反应,也不会再次评估值。试试这样的东西:

// implmeent INotifyPropertyChanged
public class TextBoxPlaceholder : IDataErrorInfo, System.ComponentModel.INotifyPropertyChanged
{
    private string mValue;
    public string Value 
    {
        get{ return mValue; }
        // fire notification
        set{mValue = value;NotifyPropertyChanged("Value");}
    }
    public event PropertyChangedEventHandler PropertyChanged;
    // helper method
    private void NotifyPropertyChanged(String info)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }
    // your code goes here