2009-04-16 22 views
21

मैंने अपनाया है जो नीचे दिखाए गए IDataErrorInfo इंटरफ़ेस और शैलियों का उपयोग करके WPF में टेक्स्टबॉक्स को मान्य करने का मानक तरीका प्रतीत होता है। हालांकि, पृष्ठ अमान्य होने पर मैं सहेजें बटन को कैसे अक्षम कर सकता हूं? क्या यह किसी भी तरह ट्रिगर्स के माध्यम से किया जाता है?सत्यापन विफल होने पर WPF में सहेजें बटन अक्षम करें

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> 

उत्तर

37

योग्य कुछ बातें:

पहले, मैं सहेजें बटन की हैंडलिंग लागू करने के लिए RoutedCommand ApplicationCommands.Save का उपयोग कर की सिफारिश करेंगे।

यदि आपने WPF कमांड मॉडल की जांच नहीं की है, तो आप here स्कूप प्राप्त कर सकते हैं।

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

अब, कार्यक्षमता लागू करने के लिए, आप एक कमांड विंडो/UserControl करने के लिए या बटन खुद के लिए बाध्य जोड़ सकते हैं:

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

के पीछे कोड में इन लागू:

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

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

Save_CanExecute में, टेक्स्ट बॉक्स पर बाध्यकारी की वैधता के आधार पर e.CanExecute सेट करें।

यदि आप एमवीवीएम (मॉडल-व्यू-व्यू मॉडेल) डिज़ाइन पैटर्न का उपयोग करके कार्यान्वित करना चाहते हैं, तो CommandSinkBinding पर जोश स्मिथ की पोस्ट देखें।

एक अंतिम ध्यान दें: आप सक्षम/जैसे ही TextBox में मूल्य बदल अपडेट किए जाने की को निष्क्रिय चाहते हैं, TextBox के लिए बाध्यकारी पर UpdateSourceTrigger="PropertyChanged" निर्धारित किया है।

संपादित करें: यदि आप नियंत्रण में सभी बाइंडिंग के आधार पर मान्य/अमान्य करना चाहते हैं, तो यहां कुछ सुझाव दिए गए हैं।

1) आप पहले से ही IDataErrorInfo लागू कर रहे हैं। IDataErrorInfo.Error प्रॉपर्टी को कार्यान्वित करने का प्रयास करें, जैसे कि यह उन स्ट्रिंग्स को लौटाता है जो आपके द्वारा बाध्यकारी सभी गुणों के लिए अमान्य है। यह केवल तभी काम करेगा यदि आपका पूरा नियंत्रण एक डेटा ऑब्जेक्ट पर बाध्यकारी है। e.CanExecute = string.IsNullOrEmpty(data.Error);

2) प्रासंगिक नियंत्रणों पर सभी सार्वजनिक स्थैतिक निर्भरताप्रॉपर्टी प्राप्त करने के लिए प्रतिबिंब का उपयोग करें। फिर प्रत्येक संपत्ति पर एक लूप में BindingOperations.GetBindingExpression(relevantControl, DependencyProperty) पर कॉल करें ताकि आप सत्यापन का परीक्षण कर सकें।

3) कन्स्ट्रक्टर में, मैन्युअल रूप से नेस्टेड नियंत्रणों पर सभी बाध्य गुणों का संग्रह बनाएं। CanExecute में, इस संग्रह के माध्यम से पुनरावृत्त करें और का उपयोग करके अभिव्यक्ति प्राप्त करने के लिए प्रत्येक DependencyObject/DepencyProperty संयोजन को मान्य करें और फिर BindingExpression.HasError की जांच करें।

+1

काम करता है महान बहुत धन्यवाद। हालांकि एक और बात है। मैं निम्नलिखित कोड के साथ व्यक्तिगत नियंत्रण की जांच कर सकता हूं यदि सत्यापन। गेटहास त्रुटि (myTextbox) तो e.CanExecute = झूठी क्या व्यक्तिगत रूप से सभी नियंत्रणों की वैधता की जांच करने का कोई तरीका है? – Mitch

+0

मैंने इस बारे में कुछ विचारों को शामिल करने के लिए संपादित किया। सुझाए गए कमांड उपयोग के लिए –

+2

+1। कमांडें हैं जो WPF ने वास्तव में मेरे लिए क्लिक करना शुरू कर दिया है। –

1

मैं सिर्फ इस बात के लिए संलग्न संपत्ति बना लिया है:

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); 
     } 
    } 
} 

मैं इसे उपयोग कर रहा हूँ इस तरह मेरी रूपों पर:

<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> 
संबंधित मुद्दे