我想使用可重用控制元件來實作 MVVM Toolkit 的驗證方法。我的問題是警告突出顯示在整個控制元件上,如下所示:

如果我不使用可重復使用的控制元件,它可以正常作業:

可重用控制元件如下所示:
ValidationTextBox.xaml
<StackPanel>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="275" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=HeaderText}" />
<TextBox
Grid.Row="1"
Text="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=TextBoxContent}" />
</Grid>
</StackPanel>
ValidationTextBox.xaml.cs
public partial class ValidationTextBox : UserControl
{
public static readonly DependencyProperty HeaderTextProperty =
DependencyProperty.Register(nameof(HeaderText), typeof(string), typeof(ValidationTextBox), new PropertyMetadata(default(string)));
public string HeaderText
{
get => (string)GetValue(HeaderTextProperty);
set => SetValue(HeaderTextProperty, value);
}
public static readonly DependencyProperty TextBoxContentProperty =
DependencyProperty.Register(nameof(TextBoxContent), typeof(string), typeof(ValidationTextBox), new FrameworkPropertyMetadata(default(string)));
public string TextBoxContent
{
get { return (string)GetValue(TextBoxContentProperty); }
set { SetValue(TextBoxContentProperty, value); }
}
public ValidationTextBox()
{
InitializeComponent();
}
}
我使用它的視圖和視圖模型:
注冊視圖.xaml
...
<controls:ValidationTextBox
Grid.Row="1"
Grid.Column="2"
MaxWidth="300"
Margin="10,10,0,0"
HeaderText="First name"
TextBoxContent="{Binding FirstName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
...
RegisterViewModel.cs
public partial class RegisterViewModel : ViewModelBase
{
...
[ObservableProperty]
[Required]
[MinLength(2)]
private string? _firstName;
...
}
如您所見,我使用 MVVM Toolkit 的源代碼生成器來處理該屬性及其驗證方法。從which implementsViewModelBase繼承。驗證作業正常,這意味著每當我輸入 2 個字符時,錯誤突出顯示就會消失,當我輸入少于 2 個字符時會重新出現。ObservableValidatorINotifyDataErrorInfo
對于第二個示例,驗證突出顯示正確顯示,我創建了一個與名字相同的屬性,我只是將文本框的文本屬性系結到該UserName屬性。
是否可以使用可重用控制元件進行驗證,或者在這種情況下需要完全不同的方法?
uj5u.com熱心網友回復:
由于驗證Binding是從視圖模型設定到 的UserControl,因此系結引擎將為 UserControl(系結目標)設定附加屬性 Validation.HasError 為 true。因此,錯誤模板是裝飾UserControl而不是特定的內部元素。
您必須配置UserControl以指示系結引擎改為裝飾不同的元素。您可以使用附加Validation.ValidationAdornerSiteFor屬性:
<UserControl>
<StackPanel>
<TextBlock />
<TextBox Validation.ValidationAdornerSiteFor="{Binding RelativeSource={RelativeSource AncestorType=UserControl}}" />
</StackPanel>
</UserControl>
我只想指出,將錯誤模板應用于完整的UserControl.
要更改此行為,您必須顯式驗證內部系結(參見下面的示例)。
由于Validation.ValidationAdornerSiteFor只允許設定單個替代元素,因此您必須手動委托驗證錯誤,以防UserControl有多個經過驗證的輸入。
以下示例顯示如何將外部系結驗證錯誤路由到相應的內部輸入元素:
MyUserControl.xaml.cs
partial class MyUserControl : UserControl
{
// This ValidationRule is only used to explicitly create a ValidationError object.
// It will never be invoked.
private class DummyValidationRule : ValidationRule
{
public override ValidationResult Validate(object value, CultureInfo cultureInfo) => throw new NotSupportedException();
}
public string TextData
{
get => (string)GetValue(TextDataProperty);
set => SetValue(TextDataProperty, value);
}
public static readonly DependencyProperty TextDataProperty = DependencyProperty.Register(
"TextData",
typeof(string),
typeof(MyUserControl),
new FrameworkPropertyMetadata(default(string), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnTextDataChanged));
private static void OnTextDataChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var userControl = (d as MyUserControl);
BindingExpression? bindingExpression = userControl.GetBindingExpression(TextDataProperty);
if (bindingExpression is null)
{
return;
}
userControl.OnTextDataChanged(bindingExpression.HasError, Validation.GetErrors(userControl).FirstOrDefault());
}
private void OnTextDataChanged(bool hasError, ValidationError validationError)
{
BindingExpression bindingExpression = this.InternalTextBox.GetBindingExpression(TextBox.TextProperty);
if (hasError)
{
validationError = new ValidationError(new DummyValidationRule(), bindingExpression, validationError.ErrorContent, validationError?.Exception);
Validation.MarkInvalid(bindingExpression, validationError);
}
else
{
Validation.ClearInvalid(bindingExpression);
}
}
}
MyUserControl.xaml
<UserControl Validation.ErrorTemplate="{x:Null}">
<StackPanel>
<TextBlock />
<TextBox x:Name="InternalTextBox"
Text="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=TextData, ValidatesOnNotifyDataErrors=True}" />
</StackPanel>
</UserControl>
<MyUserControl TextData="{Binding TextValue, ValidatesOnNotifyDataErrors=True}" />
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/479906.html
