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.GeneratedControls
是ObservableCollection<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
属性中的代码,使其每次都重新创建集合时,它工作正常。这里可能有什么问题?
我知道这可能解释得很糟糕,如果有任何误解,我会澄清的。
您的"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