ValidationRules und InputBinding

  • Modern UI

Es gibt 5 Antworten in diesem Thema. Der letzte Beitrag () ist von BornToBeRoot.

    ValidationRules und InputBinding

    Hi,

    ich habe eine ComboBox an die ValidationRules gebunden sind (Text darf nicht leer sein, Text muss eine MAC-Adresse sein).

    Spoiler anzeigen

    Quellcode

    1. <ComboBox.Text>
    2. <Binding Path="MACAddress" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged">
    3. <Binding.ValidationRules>
    4. <Validator:EmptyFieldValidator ValidatesOnTargetUpdated="True" />
    5. <Validator:MACAddressValidator ValidatesOnTargetUpdated="True"/>
    6. </Binding.ValidationRules>
    7. </Binding>
    8. </ComboBox.Text>


    Den Button aktiviere ich per Style, sofern alles in Ordnung ist...

    Spoiler anzeigen

    Quellcode

    1. <Button.Style>
    2. <Style TargetType="{x:Type Button}" BasedOn="{StaticResource ImageWithTextButton}" >
    3. <Setter Property="IsEnabled" Value="False" />
    4. <Style.Triggers>
    5. <MultiDataTrigger>
    6. <MultiDataTrigger.Conditions>
    7. <Condition Binding="{Binding Path=(Validation.HasError), ElementName=cbMACAddress}" Value="False"/>
    8. <Condition Binding="{Binding Path=(Validation.HasError), ElementName=txtBroadcast}" Value="False"/>
    9. <Condition Binding="{Binding Path=(Validation.HasError), ElementName=txtPort}" Value="False"/>
    10. </MultiDataTrigger.Conditions>
    11. <Setter Property="IsEnabled" Value="True" />
    12. </MultiDataTrigger>
    13. </Style.Triggers>
    14. </Style>
    15. </Button.Style>


    Jetzt möchte dem Benutzer aber auch die Möglichkeit geben, per Enter-Taste die Methode aufzurufen... Dazu habe ich folgenden Code in der ComboBox hinzugefügt...

    Spoiler anzeigen

    Quellcode

    1. <ComboBox.InputBindings>
    2. <KeyBinding Command="{Binding WakeUpCommand}" Key="Return" />
    3. </ComboBox.InputBindings>


    Kann mir jemand sagen wie ich prüfen kann, ob ein Fehler besteht und das ausführen der Funktion verhindern kann?

    Sitze daran schon ein paar Tage und komme leider nicht weiter. Denn Button kann ich leider nicht auf IsDefault="true" setzen.

    Wer mehr code sehen will:

    View: github.com/BornToBeRoot/NETwor…ations/WakeOnLANView.xaml
    View CS: github.com/BornToBeRoot/NETwor…ons/WakeOnLANView.xaml.cs
    ViewModel: github.com/BornToBeRoot/NETwor…ons/WakeOnLanViewModel.cs

    Danke für jede Hilfe :thumbsup:
    NETworkManager - A powerful tool for managing networks and troubleshoot network problems!
    Anstelle des InputBindings könntest Du Deinem Button die Eigenschaft IsDefault="True" geben. Dann funktioniert der wie z.B. in einer MessageBox der OK-Button. (IsCancel ist das Gegenstück dazu.)

    Ob z.B. die cbMACAddress Fehler hat, könntest Du Validation.GetHasError(cbMACAddress) verwenden:

    VB.NET-Quellcode

    1. If Not Validation.GetHasError(cbMACAddress) AndAlso _
    2. Not Validation.GetHasError(txtBroadcast) AndAlso _
    3. Not Validation.GetHasError(txtPort) Then
    4. 'Alles klar
    5. End If

    aber das ist redundant, wenn Du den ersten Vorschlag nimmst.
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils
    Aaach, und ich les mal wieder nicht den ganzen Post :D

    Wenn das ViewModel als Tag im XAML steht, müsstest Du rein theoretisch dem ViewModel eine Eigenschaft geben können:

    VB.NET-Quellcode

    1. Class DeinViewModel
    2. Public Property cbMACAddressHasError As Boolean
    3. End Class

    und dann daran binden können:

    XML-Quellcode

    1. <Irgendwas.DataContext>
    2. <DeinViewModel
    3. cbMACAddressasError="{Binding Path=(Validation.HasError), ElementName=cbMACAddress, Mode=OneWayToSource}"
    4. />
    5. </Irgendwas.DataContext>

    Beachte hier Mode=OneWayToSource. Der Wert wird nur ins ViewModel geschrieben, nie aber in die andere Richtung.

    Was anderes fällt mir da aber auch nicht ein. Muss es unbedingt im ViewModel sein?
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils
    Hab das Problem mitlerweie gelöst (ohne INotifyDataErrorInfo).
    Mit dem Post von @Niko Ortner kam ich leider auch nicht weiter. Bei meinen Recherchen bin ich auf den folgenden Beitrag gestoßen: stackoverflow.com/questions/22…haserror-property-in-mvvm


    DER CODE IST NICHT VON MIR! - Ich poste Ihn aber mal hier, falls andere auch das Problem haben.


    ProtocolSettingsLayout.cs

    C#-Quellcode

    1. using System;
    2. using System.ComponentModel;
    3. using System.Windows;
    4. using System.Windows.Controls;
    5. using System.Windows.Data;
    6. namespace EXAMPLE.Helper
    7. {
    8. public class ProtocolSettingsLayout
    9. {
    10. public static readonly DependencyProperty MVVMHasErrorProperty = DependencyProperty.RegisterAttached("MVVMHasError",
    11. typeof(bool),
    12. typeof(ProtocolSettingsLayout),
    13. new FrameworkPropertyMetadata(false,
    14. FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
    15. null,
    16. CoerceMVVMHasError));
    17. public static bool GetMVVMHasError(DependencyObject d)
    18. {
    19. return (bool)d.GetValue(MVVMHasErrorProperty);
    20. }
    21. public static void SetMVVMHasError(DependencyObject d, bool value)
    22. {
    23. d.SetValue(MVVMHasErrorProperty, value);
    24. }
    25. private static object CoerceMVVMHasError(DependencyObject d, Object baseValue)
    26. {
    27. bool ret = (bool)baseValue;
    28. if (BindingOperations.IsDataBound(d, MVVMHasErrorProperty))
    29. {
    30. if (GetHasErrorDescriptor(d) == null)
    31. {
    32. DependencyPropertyDescriptor desc = DependencyPropertyDescriptor.FromProperty(Validation.HasErrorProperty, d.GetType());
    33. desc.AddValueChanged(d, OnHasErrorChanged);
    34. SetHasErrorDescriptor(d, desc);
    35. ret = System.Windows.Controls.Validation.GetHasError(d);
    36. }
    37. }
    38. else
    39. {
    40. if (GetHasErrorDescriptor(d) != null)
    41. {
    42. DependencyPropertyDescriptor desc = GetHasErrorDescriptor(d);
    43. desc.RemoveValueChanged(d, OnHasErrorChanged);
    44. SetHasErrorDescriptor(d, null);
    45. }
    46. }
    47. return ret;
    48. }
    49. private static readonly DependencyProperty HasErrorDescriptorProperty = DependencyProperty.RegisterAttached("HasErrorDescriptor",
    50. typeof(DependencyPropertyDescriptor),
    51. typeof(ProtocolSettingsLayout));
    52. private static DependencyPropertyDescriptor GetHasErrorDescriptor(DependencyObject d)
    53. {
    54. var ret = d.GetValue(HasErrorDescriptorProperty);
    55. return ret as DependencyPropertyDescriptor;
    56. }
    57. private static void OnHasErrorChanged(object sender, EventArgs e)
    58. {
    59. DependencyObject d = sender as DependencyObject;
    60. if (d != null)
    61. {
    62. d.SetValue(MVVMHasErrorProperty, d.GetValue(Validation.HasErrorProperty));
    63. }
    64. }
    65. private static void SetHasErrorDescriptor(DependencyObject d, DependencyPropertyDescriptor value)
    66. {
    67. var ret = d.GetValue(HasErrorDescriptorProperty);
    68. d.SetValue(HasErrorDescriptorProperty, value);
    69. }
    70. }
    71. }



    TestViewModel.cs

    C#-Quellcode

    1. // Variable
    2. private bool _testHasError;
    3. public bool TestHasError
    4. {
    5. get { return _testHasError; }
    6. set
    7. {
    8. if (value == _testHasError)
    9. return;
    10. _testHasError= value;
    11. OnPropertyChanged();
    12. }
    13. }
    14. // ICommand & Action
    15. public ICommand TestCommand
    16. {
    17. get { return new RelayCommand(p => TestAction(), TestAction_CanExecute); }
    18. }
    19. private bool TestAction_CanExecute(object obj)
    20. {
    21. return !TestHasError;
    22. }
    23. private async void WakeUpAction()
    24. {
    25. // ...
    26. }



    TestView.xaml

    C#-Quellcode

    1. <TextBox x:Name="txtTest" WpfHelper:ProtocolSettingsLayout.MVVMHasError="{Binding TestHasError}">
    2. <TextBox.InputBindings>
    3. <KeyBinding Key="Enter" Command="{Binding TestCommand}" />
    4. </TextBox.InputBindings>
    5. <TextBox.Text>
    6. <Binding Path="Test" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged">
    7. <Binding.ValidationRules>
    8. <Validator:EmptyFieldValidator ValidatesOnTargetUpdated="True" />
    9. <Validator:TestValidator ValidatesOnTargetUpdated="True"/>
    10. </Binding.ValidationRules>
    11. </Binding>
    12. </TextBox.Text>
    13. </TextBox>

    NETworkManager - A powerful tool for managing networks and troubleshoot network problems!