2009-04-16 2 views
21

Ich habe die Standardmethode zur Überprüfung von Textfeldern in WPF mithilfe der IDataErrorInfo-Schnittstelle und der Stile übernommen, wie unten dargestellt. Wie kann ich jedoch die Schaltfläche "Speichern" deaktivieren, wenn die Seite ungültig wird? Wird das irgendwie durch Trigger gemacht?Deaktivieren Sie die Schaltfläche "Speichern" in WPF, wenn die Überprüfung fehlschlägt

Default Public ReadOnly Property Item(ByVal propertyName As String) As String Implements IDataErrorInfo.Item 
    Get 
     Dim valid As Boolean = True 
     If propertyName = "IncidentCategory" Then 
      valid = True 
      If Len(IncidentCategory) = 0 Then 
       valid = False 
      End If 
      If Not valid Then 
       Return "Incident category is required" 
      End If 
     End If 

     Return Nothing 

    End Get 
End Property 

<Style TargetType="{x:Type TextBox}"> 
    <Setter Property="Margin" Value="3" /> 
    <Setter Property="Height" Value="23" /> 
    <Setter Property="HorizontalAlignment" Value="Left" /> 
    <Setter Property="Validation.ErrorTemplate"> 
     <Setter.Value> 
      <ControlTemplate> 
       <DockPanel LastChildFill="True"> 
        <Border BorderBrush="Red" BorderThickness="1"> 
         <AdornedElementPlaceholder Name="MyAdorner" /> 
        </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> 

Antwort

37

Ein paar Dinge:

Zuerst würde ich empfehlen, die RoutedCommand ApplicationCommands.Save für die Umsetzung der Umgang mit der Schaltfläche Speichern.

Wenn Sie das WPF-Befehlsmodell nicht ausgecheckt haben, können Sie den Scoop here abrufen.

<Button Content="Save" Command="Save"> 

, nun die Funktionalität zu implementieren, können Sie einen Befehl Bindung an das Fenster/Usercontrol oder den Knopf selbst hinzufügen:

<Button.CommandBindings> 
     <CommandBinding Command="Save" 
         Executed="Save_Executed" CanExecute="Save_CanExecute"/> 
    </Button.CommandBindings> 
</Button> 

diese hinter im Code implementieren:

private void Save_Executed(object sender, ExecutedRoutedEventArgs e) 
{ 
} 

private void Save_CanExecute(object sender, CanExecuteRoutedEventArgs e) 
{ 
} 

Setzen Sie in Save_CanExecutee.CanExecute basierend auf der Gültigkeit der Bindung für das Textfeld.

Wenn Sie das Entwurfsmuster MVVM (Model-View-ViewModel) implementieren möchten, lesen Sie den Post von Josh Smith unter CommandSinkBinding.

Ein letzter Hinweis: Wenn Sie die Freigabe/deaktivieren möchten, sobald der Wert in der TextBox geändert werden aktualisiert, setzen UpdateSourceTrigger="PropertyChanged" auf die Bindung für die TextBox.

BEARBEITEN: Wenn Sie basierend auf allen Bindungen in der Steuerung validieren/ungültig machen möchten, hier sind ein paar Vorschläge.

1) Sie implementieren bereits IDataErrorInfo. Versuchen Sie, die IDataErrorInfo.Error -Eigenschaft so zu implementieren, dass sie die Zeichenfolge zurückgibt, die für alle Eigenschaften, an die Sie binden, ungültig ist. Dies funktioniert nur, wenn Ihr gesamtes Steuerelement an ein einzelnes Datenobjekt gebunden ist. Set e.CanExecute = string.IsNullOrEmpty(data.Error);

2) Verwenden Sie Reflektion, um alle öffentlichen statischen DependencyProperties für die relevanten Steuerelemente abzurufen. Dann rufen Sie BindingOperations.GetBindingExpression(relevantControl, DependencyProperty) in einer Schleife auf jeder Eigenschaft, damit Sie die Überprüfung testen können.

3) Erstellen Sie im Konstruktor manuell eine Auflistung aller gebundenen Eigenschaften für verschachtelte Steuerelemente. Führen Sie in CanExecute eine Iteration durch diese Auflistung durch, und validieren Sie jede DependencyObject/DepencyProperty Kombination, indem Sie verwenden, um Ausdrücke zu erhalten, und untersuchen Sie dann BindingExpression.HasError.

+1

Funktioniert prima vielen Dank. Eine andere Sache jedoch. Ich kann einzelne Steuerelemente mit dem folgenden Code überprüfen Wenn Validation.GetHasError (myTextbox) Dann e.CanExecute = False Gibt es eine Möglichkeit, die Gültigkeit aller Steuerelemente statt einzeln zu überprüfen? – Mitch

+0

Ich bearbeitet, um einige Ideen dazu zu enthalten. –

+2

+1 für die vorgeschlagene Befehlsverwendung. Befehle haben WPF veranlasst, wirklich für mich zu klicken. –

1

Ich habe angefügten Eigenschaft die gerade für diese:

public static class DataErrorInfoHelper 
{ 
    public static object GetDataErrorInfo(ButtonBase obj) 
    { 
     return (object)obj.GetValue(DataErrorInfoProperty); 
    } 

    public static void SetDataErrorInfo(ButtonBase obj, object value) 
    { 
     obj.SetValue(DataErrorInfoProperty, value); 
    } 

    // Using a DependencyProperty as the backing store for DataErrorInfo. This enables animation, styling, binding, etc... 
    public static readonly DependencyProperty DataErrorInfoProperty = 
     DependencyProperty.RegisterAttached("DataErrorInfo", typeof(object), typeof(DataErrorInfoHelper), new PropertyMetadata(null, OnDataErrorInfoChanged)); 

    private static void OnDataErrorInfoChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     var button = d as ButtonBase; 

     if (button.Tag == null) 
      button.Tag = new DataErrorInfoContext { Button = button }; 

     var context = button.Tag as DataErrorInfoContext; 

     if(e.OldValue != null) 
     { 
      PropertyChangedEventManager.RemoveHandler(((INotifyPropertyChanged)e.OldValue), context.Handler, string.Empty); 
     } 

     var inotify = e.NewValue as INotifyPropertyChanged; 
     if (inotify != null) 
     { 
      PropertyChangedEventManager.AddHandler(inotify, context.Handler, string.Empty); 
      context.Handler(inotify, new PropertyChangedEventArgs(string.Empty)); 
     } 
    } 

    private class DataErrorInfoContext 
    { 
     public ButtonBase Button { get; set; } 

     public void Handler(object sender, PropertyChangedEventArgs e) 
     { 
      var dei = sender as IDataErrorInfo; 

      foreach (var property in dei.GetType().GetProperties()) 
      { 
       if (!string.IsNullOrEmpty(dei[property.Name])) 
       { 
        Button.IsEnabled = false; 
        return; 
       } 
      } 
      Button.IsEnabled = string.IsNullOrEmpty(dei.Error); 
     } 
    } 
} 

ich es so auf meine Formularen bin:

<TextBlock Margin="2">e-mail:</TextBlock> 
<TextBox Margin="2" Text="{Binding Email, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}"/> 
<!-- other databindings---> 
<Button Margin="2" local:DataErrorInfoHelper.DataErrorInfo="{Binding}" Commands="{Binding SaveCommand}">Create account</Button> 
Verwandte Themen