2013-10-15 56 views
0

在我的應用程序中,我想驗證用戶是否在單元格中輸入新項目時輸入DataGrid上已存在的項目。我使用IDataErrorInfo驗證了我的業務對象。wpf Datagrid:拋出重複條目

我的目標如下:

class clsProducts : INotifyPropertyChanged, IDataErrorInfo 
{ 
    private string _ProductName; 
    private decimal _PurchaseRate; 
    private int _AvailableQty; 
    private int _Qty; 
    private decimal _Amount; 

    #region Property Getters and Setters 

    public string ProductName 
    { 
     get { return _ProductName; } 
     set 
     { 

      if (_ProductName != value) 
      { 
       _ProductName = value; 
       OnPropertyChanged("ProductName"); 
      } 
     } 
    } 

    public decimal PurchaseRate 
    { 
     get { return _PurchaseRate; } 
     set 
     { 
      _PurchaseRate = value; 
      OnPropertyChanged("PurchaseRate"); 
     } 
    } 

    public int AvailableQty 
    { 
     get { return _AvailableQty; } 
     set 
     { 
      _AvailableQty = value; 
      OnPropertyChanged("AvailableQty"); 
     } 
    } 

    public int Qty 
    { 
     get { return _Qty; } 
     set 
     { 
      _Qty = value; 
      this._Amount = this._Qty * this._PurchaseRate; 
      OnPropertyChanged("Qty"); 
      OnPropertyChanged("Amount"); 
     } 
    } 

    public decimal Amount 
    { 
     get { return _Amount; } 
     set 
     { 
      _Amount = value; 
      OnPropertyChanged("Amount"); 
     } 
    } 

    #endregion 

    #region IDataErrorInfo Members 

    public string Error 
    { 
     get 
     { 
      StringBuilder error = new StringBuilder(); 
      // iterate over all of the properties 
      // of this object - aggregating any validation errors 
      PropertyDescriptorCollection props = TypeDescriptor.GetProperties(this); 
      foreach (PropertyDescriptor prop in props) 
      { 
       string propertyError = this[prop.Name]; 
       if (!string.IsNullOrEmpty(propertyError)) 
       { 
        error.Append((error.Length != 0 ? ", " : "") + propertyError); 
       } 
      } 
      return error.ToString(); 
     } 
    } 

    public string this[string name] 
    { 
     get 
     { 
      string result = null; 

      if (name == "ProductName") 
      { 
       if (this._ProductName != null) 
       { 
        int count = Global.ItemExist(this._ProductName); 
        if (count == 0) 
        { 
         result = "Invalid Product "+this._ProductName; 
        } 
       } 
      } 

      else if (name == "Qty") 
      { 
       if (this._Qty > this._AvailableQty) 
       { 
        result = "Qty must be less than Available Qty . Avaialble Qty : " + this._AvailableQty; 
       } 
      } 

      return result; 
     } 
    } 

    #endregion 

    #region INotifyPropertyChanged Members 

    // Declare the event 
    public event PropertyChangedEventHandler PropertyChanged; 

    //// Create the OnPropertyChanged method to raise the event 
    protected void OnPropertyChanged(string name) 
    { 
     PropertyChangedEventHandler handler = PropertyChanged; 
     if (handler != null) 
     { 
      handler(this, new PropertyChangedEventArgs(name)); 
     } 
    } 

    #endregion 
} 

我的XAML是:

<my:DataGrid Name="dgReceiveInventory" RowStyle="{StaticResource RowStyle}" ItemsSource="{Binding}" GotFocus="dgReceiveInventory_GotFocus" CanUserDeleteRows="False" CanUserReorderColumns="False" CanUserResizeColumns="False" CanUserResizeRows="False" CanUserSortColumns="False" RowHeight="23" SelectionUnit="Cell" AutoGenerateColumns="False" Margin="12,84,10,52" BeginningEdit="dgReceiveInventory_BeginningEdit"> 
     <my:DataGrid.Columns> 

      <!--0-Product Column--> 

      <my:DataGridTemplateColumn Header="Product Name" Width="200"> 
       <my:DataGridTemplateColumn.CellTemplate> 
        <DataTemplate> 
         <TextBlock Style="{StaticResource TextBlockInError}" Text="{Binding ProductName,ValidatesOnDataErrors=True}" ></TextBlock> 
        </DataTemplate> 
       </my:DataGridTemplateColumn.CellTemplate> 
       <my:DataGridTemplateColumn.CellEditingTemplate> 
        <DataTemplate> 
         <TextBox x:Name="txtbxProduct" Style="{StaticResource TextBoxInError}" Text="{Binding Path=ProductName,UpdateSourceTrigger=LostFocus,ValidatesOnDataErrors=True}" TextChanged="txtbxProduct_TextChanged" PreviewKeyDown="txtbxProduct_PreviewKeyDown" > 
            </TextBox> 
        </DataTemplate> 
       </my:DataGridTemplateColumn.CellEditingTemplate> 
      </my:DataGridTemplateColumn> 

      <!--1-Purchase Rate Column--> 
      <my:DataGridTextColumn Header="Purchase Rate" Width="100" Binding="{Binding PurchaseRate}" IsReadOnly="True"></my:DataGridTextColumn> 

      <!--2-Avaialable Qty Column--> 
      <my:DataGridTextColumn Header="AvailableQty" Binding="{Binding AvailableQty}" IsReadOnly="True" Visibility="Hidden"></my:DataGridTextColumn> 

      <!--3-Qty Column--> 

      <my:DataGridTextColumn Header="Qty" Binding="{Binding Qty,ValidatesOnExceptions=True,ValidatesOnDataErrors=True}" EditingElementStyle="{StaticResource TextBoxInError}"> 

      </my:DataGridTextColumn> 

      <!--4-Amount Column--> 
      <my:DataGridTextColumn Header="Amount" Width="100" Binding="{Binding Amount}" ></my:DataGridTextColumn> 
     </my:DataGrid.Columns> 
    </my:DataGrid> 

現在我想告訴用戶,如果他提出的DataGrid單元格重複條目如何做到這一點?

+2

那麼問題是什麼? –

+1

1)post xaml 2)到目前爲止您嘗試過什麼? 3)你在哪裏遇到問題? –

+0

請看我的問題我編輯它 – Mussammil

回答

0

您不能在模型或數據類型類中使用IDataErrorInfo接口來執行此功能,因爲您無法訪問其中的其他對象。相反,您必須在您的視圖模型中執行此操作。但是,您可以使用該界面報告錯誤。我已經通過添加一個屬性,我的數據類型的基類擴展它的功能:

public virtual ObservableCollection<string> ExternalErrors 
{ 
    get { return externalErrors; } 
} 

正如你可以看到,礦用多個錯誤交易,但你可以很容易地將其更改爲:

public virtual string ExternalError 
{ 
    get { return externalError; } 
} 

然後我插「到這個我Errors屬性:

public override ObservableCollection<string> Errors 
{ 
    get 
    { 
     errors = new ObservableCollection<string>(); 
     errors.AddUniqueIfNotEmpty(this["Name"]); 
     errors.AddUniqueIfNotEmpty(this["EmailAddresses"]); 
     errors.AddUniqueIfNotEmpty(this["StatementPrefixes"]); 
     errors.AddRange(ExternalErrors); 
     return errors; 
    } 
} 

再次,我已經適應了這個接口返回多個錯誤,但你可以改變這:

public override string Error 
{ 
    get 
    { 
     error = string.Empty; 
     if ((error = this["Name"])) != string.Empty) return error; 
     if ((error = this["EmailAddresses"])) != string.Empty) return error; 
     if ((error = this["Name"])) != string.Empty) return error; 
     if (ExternalError != string.Empty) return ExternalError; 
     return error; 
    } 
} 

順便說一句,這是更高效的調用只是你實際驗證,而不是您的呼叫使用反射所有屬性的例子的索引。但是,那是你的選擇。

所以現在我們有了這個ExternalError屬性,我們可以使用它來顯示來自視圖模型的外部錯誤信息(創建一個包含集合屬性的類以綁定到DataGrid.ItemsSource屬性)。

如果使用ICommand對象,那麼你可以把這個代碼到你保存命令的CanExecute方法:

public bool CanSave(object parameter) 
{ 
    clsProducts instance = (clsProducts)parameter; 
    instance.ExternalError = YourCollectionProperty.Contains(instance) ? 
     "The values must be unique" : string.Error; 
    // Perform your can save checks here 
} 

請注意,您將需要實現Equals方法爲您的數據類型的對象這工作。有很多類似的方法來實現這一點,我相信從這個例子中你將能夠爲你工作一個。