开发者

WPF how to prevent Save on empty data entry dialog

I have a dialog with a few fields. Some of them use validation - ValidatesOnExceptions=True in my case.

I have a data object with INotifyPropertyChanged that I bind to dialogs' DataContext.

I also have a "Save" button. Validation works fine, but only after I edit each field.

If dialog is opened and closed immediately, validation will not fire.

What should I do prevent Save from firing in this case (use case: ope开发者_开发问答n dialog, press save immediately)


Use command bindings for the save button, then you can enable/disable the button depending on your current state

see this simple tutorial and if you want further explantion the msdn article, also josh smith gets more in depth

We handle your above situation by using a combination of commands and an IsValid property on the underlying model we are binding to. We do validation at the business model level (some times in the ui as well) and when the business model is valid we enable the command, or as in your case, save button.

Here is a sample of the style we apply to our text boxes (we derive from text box and give it another property called SimpleField. This field has the properties IsValid, IsDirty, IsReadOnly, ErrorMessage and DatabaseValue. This enables us to know if the field is valid, whether it has changed if it is read only (i.e. the user doesnt have the permission to change the value or it is locked for another reason), if there is an error message (associated with the IsValid property) and also the database value (for when the field has changed, the user can see the original value) We use all of these properties in the style below

   <!-- Simple TextBox -->
   <Style
      TargetType="{x:Type local:SimpleFieldTextBox}"
      BasedOn="{StaticResource {x:Type TextBox}}">
      <Setter
         Property="KeyboardNavigation.TabNavigation"
         Value="None" />
      <Setter
         Property="FocusVisualStyle"
         Value="{x:Null}" />
      <Setter
         Property="AllowDrop"
         Value="True" />
      <Setter
         Property="SnapsToDevicePixels"
         Value="True" />
      <Setter
         Property="Height"
         Value="22" />
      <Setter
         Property="Template">
         <Setter.Value>
            <ControlTemplate
               TargetType="{x:Type local:SimpleFieldTextBox}">

               <Border
                  x:Name="PART_SimpleFieldTextBox"
                  Background="{TemplateBinding Background}"
                  BorderBrush="{TemplateBinding BorderBrush}"
                  BorderThickness="{TemplateBinding BorderThickness}"
                  Height="{TemplateBinding Height}"
                  SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}">

                  <Grid>
                     <Grid.ColumnDefinitions>
                        <ColumnDefinition
                           Width="Auto" />
                        <ColumnDefinition
                           Width="*" />
                     </Grid.ColumnDefinitions>

                     <!-- The implementation places the Content into the ScrollViewer.
                          It must be named PART_ContentHost for the control to function -->
                     <ScrollViewer
                        x:Name="PART_ContentHost"
                        Grid.Column="1"
                        Margin="0" />


                     <!-- Not Valid Icon -->
                     <Path
                        x:Name="IconError"
                        Grid.Column="0"
                        Fill="Red"
                        Stretch="Fill"
                        Margin="1,1,4,1"
                        HorizontalAlignment="Left"
                        VerticalAlignment="Top"
                        Visibility="Collapsed"
                        Width="4"
                        Height="14"
                        SnapsToDevicePixels="True"
                        Data="M0,11 L6,11 6,14 0,14 z M0,0 L6,0 6,10 0,10 z">
                        <Path.ToolTip>
                           <ToolTip>
                              <StackPanel
                                 Orientation="Vertical"
                                 MaxWidth="300"
                                 MaxHeight="100">
                                 <TextBlock
                                    FontStyle="Italic"
                                    Text="Error:" />
                                 <TextBlock
                                    Margin="8,0,0,0"
                                    TextWrapping="WrapWithOverflow"
                                    TextTrimming="CharacterEllipsis"
                                    Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=SimpleField.ErrorMessage}" />
                                 <TextBlock
                                    Margin="0,4,0,0"
                                    FontStyle="Italic"
                                    Text="Original Value: " />
                                 <TextBlock
                                    Margin="8,0,0,0"
                                    TextWrapping="WrapWithOverflow"
                                    TextTrimming="CharacterEllipsis"
                                    Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=SimpleField.DatabaseValue}" />
                              </StackPanel>
                           </ToolTip>
                        </Path.ToolTip>
                     </Path>


                     <!-- Valid (but changed) Icon-->
                     <Path
                        x:Name="IconWarning"
                        Grid.Column="0"
                        Fill="#FF5BBD30"
                        Stretch="Fill"
                        Margin="1,1,0,0"
                        HorizontalAlignment="Left"
                        VerticalAlignment="Top"
                        Visibility="Collapsed"
                        Width="8"
                        Height="8"
                        SnapsToDevicePixels="True"
                        Data="M0,0 L8,0 0,8 z">
                        <Path.ToolTip>
                           <ToolTip>
                              <StackPanel
                                 Orientation="Vertical"
                                 MaxWidth="500"
                                 MaxHeight="100">
                                 <TextBlock
                                    Text="Original Value: " />
                                 <TextBlock
                                    Margin="8,0,0,0"
                                    TextWrapping="Wrap"
                                    TextTrimming="CharacterEllipsis"
                                    Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=SimpleField.DatabaseValue}" />
                              </StackPanel>
                           </ToolTip>
                        </Path.ToolTip>
                     </Path>
                  </Grid>
               </Border>
               <ControlTemplate.Triggers>

                  <!-- Stop the text box being edited if the simple field is read only -->
                  <DataTrigger
                     Binding="{Binding RelativeSource={RelativeSource Self}, Path=SimpleField.IsReadOnly}"
                     Value="True">
                     <Setter
                        Property="IsReadOnly"
                        Value="True" />
                     <Setter
                        Property="Foreground"
                        Value="{StaticResource DisabledForegroundBrush}" />
                     <Setter
                        TargetName="PART_SimpleFieldTextBox"
                        Property="Background"
                        Value="{StaticResource DisabledBackgroundBrush}" />
                     <Setter
                        TargetName="PART_SimpleFieldTextBox"
                        Property="BorderBrush"
                        Value="{StaticResource DisabledBorderBrush}" />
                  </DataTrigger>

                  <!-- IsEnabled condition -->
                  <DataTrigger
                     Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsEnabled}"
                     Value="False">
                     <Setter
                        Property="Foreground"
                        Value="{StaticResource DisabledForegroundBrush}" />
                     <Setter
                        TargetName="PART_SimpleFieldTextBox"
                        Property="Background"
                        Value="{StaticResource DisabledBackgroundBrush}" />
                     <Setter
                        TargetName="PART_SimpleFieldTextBox"
                        Property="BorderBrush"
                        Value="{StaticResource DisabledBorderBrush}" />
                  </DataTrigger>

                  <!-- When value inside field has been changed -->
                  <DataTrigger
                     Binding="{Binding RelativeSource={RelativeSource Self}, Path=SimpleField.IsDirty}"
                     Value="True">
                     <Setter
                        TargetName="IconWarning"
                        Property="Visibility"
                        Value="Visible" />
                  </DataTrigger>

                  <!-- When value inside field is NOT valid -->
                  <DataTrigger
                     Binding="{Binding RelativeSource={RelativeSource Self}, Path=SimpleField.IsValid}"
                     Value="False">
                     <Setter
                        TargetName="IconWarning"
                        Property="Visibility"
                        Value="Collapsed" />
                     <Setter
                        TargetName="IconError"
                        Property="Visibility"
                        Value="Visible" />
                  </DataTrigger>
               </ControlTemplate.Triggers>
            </ControlTemplate>
         </Setter.Value>
      </Setter>
   </Style>
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜