我想要完成的是能够验证输入到可编辑组合框中的新类别,或者从现有的组合框列表中选择一个。
验证仅适用于selectedItem,不适用于输入Text的新文本。只要我将ValidateOnDataErrors="True"
添加到ComboBox'es Text属性,就不会触发输入新文本的事件。 Category是一个带有Id和Name的简单对象。
XAML:
<Window.Resources>
<ControlTemplate x:Key="ValidationErrorTamplate">
<Border BorderBrush="DodgerBlue" BorderThickness="0.75">
<AdornedElementPlaceholder />
</Border>
</ControlTemplate>
<Style x:Key="ElementInError" TargetType="{x:Type FrameworkElement}">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="ToolTip" Value="{Binding (Validation.Errors)[0].ErrorContent, RelativeSource={x:Static RelativeSource.Self}}" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<ComboBox Name="CbCategory"
DisplayMemberPath="Name"
IsEditable="True"
ItemsSource="{Binding Categories}"
SelectedItem="{Binding SelectedCategory,
UpdateSourceTrigger=PropertyChanged,
ValidatesOnDataErrors=True}"
Style="{StaticResource ElementInError}"
Text="{Binding NewCategory.Name,
UpdateSourceTrigger=PropertyChanged,
ValidatesOnDataErrors=True}"
Validation.ErrorTemplate="{StaticResource ValidationErrorTamplate}" />
ViewModel:(: IDataErrorInfo
)
private Category _newCategory;
private Category _selectedCategory;
public ExpenseCategory SelectedCategory
{
get { return _selectedCategory; }
set
{
if (Equals(_selectedCategory, value)) return;
_selectedCategory = value;
SendPropertyChanged("SelectedCategory");
}
}
public ExpenseCategory NewExpenseCategory
{
get { return _newExpenseCategory ?? (_newExpenseCategory = new ExpenseCategory()); }
set
{
if (Equals(_newExpenseCategory, value)) return;
_newExpenseCategory = value;
SendPropertyChanged("NewExpenseCategory");
}
}
public string this[string propertyName]
{
get
{
switch (propertyName)
{
case "SelectedExpenseCategory":
case "NewExpenseCategory":
{
if ((SelectedCategory == null) || (NewCategory == null)
{
return "Category must be selected or entered";
}
}
break;
}
return string.Empty;
}
答案 0 :(得分:1)
让它工作,它可能不是一流的方式,但它完成了工作。
我基本上做了什么,我将NewCategory更改为字符串,而不是Category类型的对象。当用户将新值填充到组合框中时,它会根据传递给NewCategory构造函数的值启动新的SelectedCategory。如果我保留对象类型Category的NewCategory,它就不起作用。
public string NewExpenseCategory
{
get { return _newExpenseCategory ?? (_newExpenseCategory = ""); }
set
{
if (Equals(_newExpenseCategory, value))
return;
_newExpenseCategory = value;
SendPropertyChanged("NewExpenseCategory");
SelectedExpenseCategory = new ExpenseCategory
{
Name = value
};
}
}
public string this[string propertyName]
{
get
{
switch (propertyName)
{
case "SelectedExpenseCategory":
case "NewExpenseCategory":
{
if ((SelectedExpenseCategory.Name.Length == 0) && (NewExpenseCategory.Length == 0))
{
return "Category must be selected or entered";
}
}
break;
}
return string.Empty;
}
}