简体   繁体   中英

Validating UserControl's control by Window's ViewModel

Suppose, I have created custom LoginForm as an UserControl , which consists of TextBox and PasswordBox . TextBox has installed custom ErrorTemplate . Naturally, I would like to have this LoginForm as reusable as can, therefore I want to separate validation logic from this LoginForm.

The problem is, that if I bind LoginForm's text property to the "validation-property" of the ViewModel : IDataErrorInfo , that is set as Window 's DataContext , the ErrorTemplate is not being applied to LoginForm's TextBox even if I see debug logs from ViewModel's validator.

How can I validate child controls of reusable component via independent ViewModel?

use this error template in application resource:

<Style TargetType="{x:Type TextBox}">
    <Setter Property="Validation.ErrorTemplate">
        <Setter.Value>
            <ControlTemplate>
                <DockPanel LastChildFill="True">
                    <Border BorderBrush="Red" BorderThickness="0.8">
                        <AdornedElementPlaceholder Name="adornerPlaceholder"></AdornedElementPlaceholder>
                    </Border>
                </DockPanel>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <Trigger Property="Validation.HasError" Value="true">
            <Setter Property="ToolTip"
              Value="{Binding RelativeSource={RelativeSource Self},
                    Path=(Validation.Errors)[0].ErrorContent}" />
        </Trigger>
    </Style.Triggers>
</Style>

After hours of struggling how to solve this, I came up with following solution which satisfies my requirements and so MVVM pattern:

  1. Create in UserControl a DepdendencyProperty of type IDataErrorInfo which will be later implemented by your ViewModel (for my purposes, I used ISignUpValidator :IDataErrorInfo with UsernameValue property). Lets say this property is registered under the name Validator (as default value I used "do-nothing" implementation of my interface).
  2. Bind UserControl 's TextBox.Text property to Validator property: Lets say TextBox.Text property is exposed to UserControl under the name Username :

     Username="{Binding Path=Validator.UsernameValue, ElementName=UserControlName, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" 
  3. Finally Bind your Viewmodel to your UserControl 's Validator property

     <Window.Resources> <local:ViewModel x:Key="ViewModel"/> <Window.Resources> <local:LoginForm Validator={StaticResource ViewModel}> 

    Or alternatively, if your ViewModel is already set as Window 's DataContext :

     <local:LoginForm Validator="{Binding DataContext, ElementName=WindowName}"}> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM