2011-11-16 50 views
2

我有一個由TabControl組成的WPF應用程序。我做了它的一個簡單的版本爲這個問題的目的:如何禁用基於WPF驗證的一些控件?

enter image description here

在第一個選項卡我有組合框填充一個DataGrid。如果我在數據網格中選擇了一行,它會綁定幾個文本框,用戶可以編輯它的內容。

我在datagrid中的對象實現了IDataErrorInfo接口,我的文本框在{binding}中設置了ValidatesOnDataErrors = True。所以,如果我刪除名稱的文本框的內容,它變得無效(後文本框失去焦點):

enter image description here

現在,如果它是無效的,我不希望用戶能夠選擇另一行在數據網格中,或者在組合框中選擇另一行(這將重新填充數據網格)。基本上我希望用戶在他/她繼續之前更正名稱。雖然,我寧願如果用戶可以切換標籤。

所以我要麼禁用左側的控件,如果綁定的對象無效,或者我需要將焦點設置爲無效的文本框,如果我點擊左側的控件。我沒有發現任何合適的事件或綁定。所有的想法都讚賞。

這是我的XAML:

<Window x:Class="WpfValidationTest.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="350" Width="350"> 
    <TabControl> 
     <TabItem Header="Tab 1"> 
      <StackPanel Orientation="Horizontal"> 
       <StackPanel Orientation="Vertical"> 
        <ComboBox> 
         <ComboBox.Items> 
          <ComboBoxItem Content="Friends"/> 
          <ComboBoxItem Content="Business"/> 
         </ComboBox.Items> 
        </ComboBox> 
        <DataGrid Name="dg" AutoGenerateColumns="False"> 
         <DataGrid.Columns> 
          <DataGridTextColumn Header="Name" Binding="{Binding Name}" /> 
          <DataGridTextColumn Header="Address" Binding="{Binding Address}" /> 
         </DataGrid.Columns> 
        </DataGrid> 
       </StackPanel> 

       <StackPanel Orientation="Vertical" Width="200" Margin="10,0,0,0"> 
        <TextBlock Text="Edit" FontWeight="Bold"/> 
        <TextBlock Text="Name:"/> 
        <TextBox Text="{Binding Path=SelectedItem.Name, ElementName=dg, ValidatesOnDataErrors=True}" /> 
        <TextBlock Text="Address:"/> 
        <TextBox Text="{Binding Path=SelectedItem.Address, ElementName=dg, ValidatesOnDataErrors=True}" /> 
       </StackPanel> 
      </StackPanel> 
     </TabItem> 

     <TabItem Header="Tab 2"> 
      <TextBlock Text="The user should be able to navigate to this tab even if there are validation errors" TextWrapping="Wrap" /> 
     </TabItem> 
    </TabControl> 

</Window> 

這裏是後面的代碼:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Data; 
using System.Windows.Documents; 
using System.Windows.Input; 
using System.Windows.Media; 
using System.Windows.Media.Imaging; 
using System.Windows.Navigation; 
using System.Windows.Shapes; 
using System.ComponentModel; 

namespace WpfValidationTest 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 

      List<Person> persons = new List<Person>() 
      { 
       new Person(){Name="John Doe", Address="My street 203"}, 
       new Person(){Name="Jane Doe", Address="Your street 43"} 
      }; 
      dg.ItemsSource = persons; 
     } 
    } 

    public class Person : INotifyPropertyChanged, IDataErrorInfo 
    { 
     public event PropertyChangedEventHandler PropertyChanged; 

     public string Error 
     { 
      get { throw new NotImplementedException(); } 
     } 

     public string this[string columnName] 
     { 
      get 
      { 
       switch (columnName) 
       { 
        case "Name": 
         if (string.IsNullOrEmpty(Name)) 
          return "Name must be entered"; 
         break; 
        case "Address": 
         if (string.IsNullOrEmpty(Address)) 
          return "Address must be entered"; 
         break; 
       } 
       return null; 
      } 
     } 

     private string _name; 
     public string Name 
     { 
      get { return _name; } 
      set 
      { 
       _name = value; 
       NotifyPropertyChanged("Name"); 
      } 
     } 

     private string _address; 
     public string Address 
     { 
      get { return _address; } 
      set 
      { 
       _address = value; 
       NotifyPropertyChanged("Address"); 
      } 
     } 

     private void NotifyPropertyChanged(string propName) 
     { 
      if (PropertyChanged != null) 
       PropertyChanged(this, new PropertyChangedEventArgs(propName)); 
     } 
    } 
} 
+0

謝謝Merlyn Morgan-格雷厄姆添加圖像。自從我是新成員後,我無法添加它們。 –

回答

3

您可以使用觸發器來禁用該控件

 <Style x:Key="disableOnValidation" 
      BasedOn="{StaticResource {x:Type DataGrid}}" 
      TargetType="{x:Type DataGrid}"> 
     <Style.Triggers> 
      <DataTrigger Binding="{Binding ElementName=nameTextBox, Path=Validation.HasError}" Value="True"> 
       <Setter Propert="IsEnabled" Value="False" /> 
      </DataTrigger> 
      <DataTrigger Binding="{Binding ElementName=addressTextbox, Path=Validation.HasError}" Value="True"> 
       <Setter Propert="IsEnabled" Value="False" /> 
      </DataTrigger> 
     </Style.Triggers> 
    </Style> 
+1

謝謝adcool2007,它幾乎奏效。 我不得不改變綁定路徑爲(Validation.HasError),因爲這篇文章說:http://stackoverflow.com/questions/4055226/wpf-combobox-validation-trigger 另一個問題是,當IsEnabled設置爲假數據網格的SelectedItem變爲null。 所以我把它改爲: 用戶可STIL標籤到數據網格雖然:-( –

+0

@的Björn沒有你的設置SelectedItemin數據網格的給你視圖模型的結合屬性,如'SelectedItem = {Binding Path = MySelectedItem,Mode = TwoWay}'?? – Ankesh

+0

我沒有使用viewmodel作爲我的簡單例子,但我現在嘗試了一下你的綁定表達式,但我仍然遇到同樣的問題: datagrid被禁用,SelectedItem被設置爲null,這使得我的視圖模型中的屬性也爲null。 –