gpt4 book ai didi

c# - MVVM 中的绑定(bind) Validation.HasError 属性

转载 作者:太空狗 更新时间:2023-10-29 21:27:47 25 4
gpt4 key购买 nike

我目前正在实现 ValidationRule 来检查 TextBox 中是否存在某些无效字符。我很高兴在我的 TextBox 上设置继承 ValidationRule 的类,当发现此类字符时将其设置为红色,但我也想使用 Validation.HasError 属性或 Validation.Errors 属性弹出一个消息框,告诉用户页面的各种文本框中存在错误。

有没有办法将我的 ViewModel 中的属性绑定(bind)到 Validation.HasError 和/或中的 Validation.Errors 属性命令让我在我的 ViewModel 中访问它们?

这是我的 TextBox 错误样式:

<Style x:Key="ErrorValidationTextBox" TargetType="{x:Type pres:OneTextBox}">
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<DockPanel LastChildFill="True">
<TextBlock DockPanel.Dock="Right"
Foreground="Red"
FontSize="12pt"
Text="{Binding ElementName=MyAdorner,
Path=AdornedElement.(Validation.Errors)[0].ErrorContent}">
</TextBlock>
<AdornedElementPlaceholder x:Name="MyAdorner"/>
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

这是我在我的 XAML 中声明我的 TextBox(OneTextBox 封装常规 WPF TextBox)的方式:

<pres:OneTextBox Watermark="Name..." Margin="85,12,0,0" Style="{StaticResource ErrorValidationTextBox}"
AcceptsReturn="False" MaxLines="1" Height="22" VerticalAlignment="Top"
HorizontalAlignment="Left" Width="300" >
<pres:OneTextBox.Text>
<Binding Path="InterfaceSpecification.Name" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<interfaceSpecsModule:NoInvalidCharsRule/>
</Binding.ValidationRules>
</Binding>
</pres:OneTextBox.Text>
</pres:OneTextBox>

最佳答案

Validation.HasError只读 属性,因此Binding 不适用于此属性。这可以在 ILSpy 中看到:

public virtual bool HasError
{
get
{
return this._validationError != null;
}
}

作为替代方案,您应该会看到一个很棒的 article它以使用附加依赖属性的形式提供了一个解决方案,您将在其中看到该示例的详细说明。

下面是这篇文章的完整示例,我只是在C#下翻译的,原文是VB.NET:

XAML

<Window x:Class="HasErrorTestValidation.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:HasErrorTestValidation"
WindowStartupLocation="CenterScreen"
Title="MainWindow" Height="350" Width="525">

<Window.DataContext>
<local:TestData />
</Window.DataContext>

<StackPanel>
<TextBox x:Name="TestTextBox"
local:ProtocolSettingsLayout.MVVMHasError="{Binding Path=HasError}">
<TextBox.Text>
<Binding Path="TestText" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<local:OnlyNumbersValidationRule ValidatesOnTargetUpdated="True"/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>

<TextBlock>
<TextBlock.Text>
<Binding Path="HasError" StringFormat="HasError is {0}"/>
</TextBlock.Text>
</TextBlock>

<TextBlock>
<TextBlock.Text>
<Binding Path="(Validation.HasError)" ElementName="TestTextBox" StringFormat="Validation.HasError is {0}"/>
</TextBlock.Text>
</TextBlock>
</StackPanel>
</Window>

代码隐藏

public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}

#region Model

public class TestData : INotifyPropertyChanged
{
private bool _hasError = false;

public bool HasError
{
get
{
return _hasError;
}

set
{
_hasError = value;
NotifyPropertyChanged("HasError");
}
}

private string _testText = "0";

public string TestText
{
get
{
return _testText;
}

set
{
_testText = value;
NotifyPropertyChanged("TestText");
}
}

#region PropertyChanged

public event PropertyChangedEventHandler PropertyChanged;

protected void NotifyPropertyChanged(string sProp)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(sProp));
}
}

#endregion
}

#endregion

#region ValidationRule

public class OnlyNumbersValidationRule : ValidationRule
{
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
var result = new ValidationResult(true, null);

string NumberPattern = @"^[0-9-]+$";
Regex rgx = new Regex(NumberPattern);

if (rgx.IsMatch(value.ToString()) == false)
{
result = new ValidationResult(false, "Must be only numbers");
}

return result;
}
}

#endregion

public class ProtocolSettingsLayout
{
public static readonly DependencyProperty MVVMHasErrorProperty= DependencyProperty.RegisterAttached("MVVMHasError",
typeof(bool),
typeof(ProtocolSettingsLayout),
new FrameworkPropertyMetadata(false,
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
null,
CoerceMVVMHasError));

public static bool GetMVVMHasError(DependencyObject d)
{
return (bool)d.GetValue(MVVMHasErrorProperty);
}

public static void SetMVVMHasError(DependencyObject d, bool value)
{
d.SetValue(MVVMHasErrorProperty, value);
}

private static object CoerceMVVMHasError(DependencyObject d,Object baseValue)
{
bool ret = (bool)baseValue;

if (BindingOperations.IsDataBound(d,MVVMHasErrorProperty))
{
if (GetHasErrorDescriptor(d)==null)
{
DependencyPropertyDescriptor desc = DependencyPropertyDescriptor.FromProperty(Validation.HasErrorProperty, d.GetType());
desc.AddValueChanged(d,OnHasErrorChanged);
SetHasErrorDescriptor(d, desc);
ret = System.Windows.Controls.Validation.GetHasError(d);
}
}
else
{
if (GetHasErrorDescriptor(d)!=null)
{
DependencyPropertyDescriptor desc= GetHasErrorDescriptor(d);
desc.RemoveValueChanged(d, OnHasErrorChanged);
SetHasErrorDescriptor(d, null);
}
}

return ret;
}

private static readonly DependencyProperty HasErrorDescriptorProperty = DependencyProperty.RegisterAttached("HasErrorDescriptor",
typeof(DependencyPropertyDescriptor),
typeof(ProtocolSettingsLayout));

private static DependencyPropertyDescriptor GetHasErrorDescriptor(DependencyObject d)
{
var ret = d.GetValue(HasErrorDescriptorProperty);
return ret as DependencyPropertyDescriptor;
}

private static void OnHasErrorChanged(object sender, EventArgs e)
{
DependencyObject d = sender as DependencyObject;

if (d != null)
{
d.SetValue(MVVMHasErrorProperty, d.GetValue(Validation.HasErrorProperty));
}
}

private static void SetHasErrorDescriptor(DependencyObject d, DependencyPropertyDescriptor value)
{
var ret = d.GetValue(HasErrorDescriptorProperty);
d.SetValue(HasErrorDescriptorProperty, value);
}
}

作为使用 ValidationRule 的替代方法,您可以在 MVVM 风格中尝试实现 IDataErrorInfo界面。有关更多信息,请参见:

Enforcing Complex Business Data Rules with WPF

关于c# - MVVM 中的绑定(bind) Validation.HasError 属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22827437/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com