我必须构建一个自定义控件。简单的TextBox内置验证,我可以在我的应用程序的不同部分使用。 我是这样做的:
ValidTextBoxVM代码:
public class ValidTextBoxVM : INotifyPropertyChanged
{
#region INotifyPropertyChange implementation
private String _number;
public String Number
{
get { return _number; }
set
{
if (_number != value)
{
Validate(value);
_number = value;
RaisePropertyChanged("Number");
}
}
}
private void Validate(string number)
{
if (!string.IsNullOrEmpty(number) && number.Length > 10)
{
throw new ArgumentOutOfRangeException("Number too long.");
}
}
}
ValidTextBox.xaml代码:
<TextBox x:Class="WpfApplication1.ValidTextBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="clr-namespace:WpfApplication1"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
Text="{Binding Number, ValidatesOnExceptions=True, UpdateSourceTrigger=LostFocus}">
<TextBox.DataContext>
<vm:ValidTextBoxVM/>
</TextBox.DataContext>
</TextBox>
我把我的控制权放在MainWindow上,它运作得很好。虽然失去了焦点 - 如果验证过程没有通过,ViewModel会引发异常 - 那就没问题(下面的代码)。
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ctrl="clr-namespace:WpfApplication1"
xmlns:vm="clr-namespace:WpfApplication1"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<ctrl:ValidTextBox Margin="5" Width="200" HorizontalAlignment="Left"/>
</StackPanel>
</Window>
当我为MainWindow(MainWindowVM)使用单独的viewmodel并将我的控件的Text属性与MainWindowVM中的field(MainNumber)绑定时,情况发生了变化。 它隐藏了我以前的绑定和验证已经停止工作(下面的代码)。
<StackPanel>
<ctrl:ValidTextBox Text="{Binding MainNumber, ValidatesOnExceptions=True, UpdateSourceTrigger=LostFocus}" Margin="5" Width="200" HorizontalAlignment="Left"/>
</StackPanel>
是否有任何模式可以创建自我验证控件。我找到了许多解决方案,但验证过程不受控制。
答案 0 :(得分:1)
问题是在DataContext
上设置了TextBox
。这意味着当你写:
<ctrl:ValidTextBox Text="{Binding MainNumber
...框架将尝试解析ctrl:ValidTextBox
对象上的“MainNumber”,该对象是对象的DataContext。 (这是违反直觉的,但这就是它的工作原理 - 如果检查Visual Studio“输出”,你应该能够在对象“ValidTextBox”上找到“无法找到属性”MainNumber“的绑定错误”窗口。)
我发现使用特定于控件的视图模型通常很棘手,并且会导致并发症。我建议尽可能避免这种做法。在这种情况下,为什么不只是扩展TextBox
并为LostFocus
事件添加验证处理程序?
public class ValidTextBox : TextBox
{
public ValidTextBox()
{
LostFocus += ValidTextBox_LostFocus;
}
void ValidTextBox_LostFocus(object sender, System.Windows.RoutedEventArgs e)
{
// TODO validate
}
}