Search code examples
wpfmvvmmaterial-design-in-xaml

MaterialDesignInXaml validation in dialogs - how to compare 2 textboxes?


I'm trying to write simple WPF application with MVVM pattern(, eactiveUI and MaterialDesignInXaml. On a main window I have DialogHost with 2 textboxes, then cancel and save buttons. The dialog is stored as resource and opened from main window View Model by passing EmployeeViewModel View model. That view model contains just 2 properties: EmployeeSurname and EmployeeName(not like a really view model I know, but its to be used in dialog host and to get data from it). I have also simple validation rule in separate class (not included here) which I added via xaml to one of my text boxes currently. The basic things validation work fine on single element but I'd like to achieve more, particularily:

  1. How to compare 2 or more checkboxes? I can't pass data from another text box to validation rule, it works only on the current textbox where the rule is assigned.
  2. How to display another dialog on top of existing one(iex. ask for confirmation before closing the dialog to save changes) - is it correct approach?
  3. How to have the Save button disabled initially when the dialog is opened (so it will be enabled when the user types correct value first time)? That one looks quite easy ad I was easily able to use commands on main window to do this, but with that routed commands used in MaterialDesignInXaml dialog buttons I'm not sure how to achieve this
  • I know how to enable / disable save button when the user enter some data but how to have it disabled initially. I tryied to add disable button by estting that property directly on xaml but then it is permanent. Sounds realtively easy but I'm stuck on that things now.

XAML

     <DataTemplate DataType="{x:Type local:EmployeeViewModel}">

TextBox1:

                <TextBox Name="txtEmployeeName" MaxLength="8">
                <TextBox.Text>
                    <Binding Path="EmployeeName" UpdateSourceTrigger="PropertyChanged">
                        <Binding.ValidationRules>
                            <VR:NameSurnameRule/>
                        </Binding.ValidationRules>
                    </Binding>
                </TextBox.Text>
            </TextBox>

TextBox2(it does not have any validation yet):

<TextBox Name="txtSurname" Text="{Binding EmployeeSurname, UpdateSourceTrigger=PropertyChanged}" />

Save Button:

            <Button Content="_Login" Command="{x:Static md:DialogHost.CloseDialogCommand}" Grid.Row="1" Grid.Column="2">
            <Button.CommandParameter> 
                <system:Boolean>True</system:Boolean>
            </Button.CommandParameter>
            <Button.Style>
                <Style TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding Path=(Validation.HasError), ElementName=txtEmployeeName}" Value="True">
                            <Setter Property="IsEnabled" Value="False" />
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </Button.Style>
        </Button>

Cancel button

<Button Content="_Cancel" Command="{x:Static md:DialogHost.CloseDialogCommand}" Grid.Row="1" Grid.Column="0" />

That dialog is in resource, No codebehind. Thanks in advance


Solution

  • You can pass something to validation rule with wrapper approach, good example is here. Or you can use IErrorDataInfo in your Model for validation (or combine this aproach with Rule validation, but attach rule in your view model). For first validation you can raise PropertyChanged in ViewModel constructor, it forces validation for first time.