wpf Datagrid:单击保存按钮时获取验证错误

时间:2013-10-08 05:54:05

标签: c# wpf validation datagrid wpftoolkit

我有一个数据网格,我使用IDataErrorInfo进行验证。现在我想在单击保存按钮时验证失败时显示错误消息。我的问题是如何获得验证错误,我在网上尝试了很多页面我真的厌倦了这些人知道解决方案吗? 我的数据网格是:

 <my:DataGrid Name="dgDamagedProducts" ItemsSource="{Binding}"   SelectionUnit="Cell"  BeginningEdit="dgDamagedProducts_BeginningEdit"  AutoGenerateColumns="False" Margin="13,75,9,117" RowEditEnding="dgDamagedProducts_RowEditEnding" GotFocus="dgDamagedProducts_GotFocus">
                    <my:DataGrid.Columns>
                        <!--0-ProductTransaction ID Column-->
                        <my:DataGridTextColumn  Header="ProductTransaction ID"  Visibility="Hidden" Width="0" Binding="{Binding ProductTransactionID}"></my:DataGridTextColumn>
                        <!--1-Item incID Column-->
                        <my:DataGridTextColumn  Header="ItemID" Visibility="Hidden" Width="0" Binding="{Binding ItemID}"></my:DataGridTextColumn>
                        <!--2-Product Code Column-->
                        <my:DataGridTextColumn  Header="Code" Width="100" Binding="{Binding ProductCode}"></my:DataGridTextColumn>
                        <!--3-Product Column-->
                        <my:DataGridTemplateColumn Header="Product Name" Width="200">
                            <my:DataGridTemplateColumn.CellTemplate>
                                <DataTemplate>
                                    <TextBlock Padding="3" Text="{Binding ProductName,NotifyOnValidationError=True,ValidatesOnDataErrors=True}" Style="{StaticResource TextBlockInError}"></TextBlock>
                                </DataTemplate>
                            </my:DataGridTemplateColumn.CellTemplate>
                            <my:DataGridTemplateColumn.CellEditingTemplate>
                                <DataTemplate>
                                    <TextBox x:Name="txtbxProduct" Style="{StaticResource TextBoxInError}" Text="{Binding Path=ProductName,Mode=TwoWay,NotifyOnValidationError=True,ValidatesOnDataErrors=True}" lc:FocusAttacher.Focus="True" TextChanged="txtbxProduct_TextChanged" PreviewKeyDown="txtbxProduct_PreviewKeyDown" ></TextBox>
                                </DataTemplate>
                            </my:DataGridTemplateColumn.CellEditingTemplate>
                        </my:DataGridTemplateColumn>

                        <!--7-Purchase Rate Column-->
                        <my:DataGridTextColumn Header="Purchase Rate" Width="100" Binding="{Binding PurchaseRate}" IsReadOnly="True"></my:DataGridTextColumn>
                        <!--8-Stock  Column-->
                        <my:DataGridTextColumn Header="Stock"  Binding="{Binding AvailableQty}" IsReadOnly="True" Visibility="Hidden"></my:DataGridTextColumn>
                        <!--9-Qty Column-->
                        <my:DataGridTemplateColumn Header="Qty" Width="100">
                            <my:DataGridTemplateColumn.CellTemplate>
                                <DataTemplate>
                                    <TextBlock Text="{Binding Qty,ValidatesOnDataErrors=True}" Style="{StaticResource TextBlockInError}"></TextBlock>
                                </DataTemplate>
                            </my:DataGridTemplateColumn.CellTemplate>
                            <my:DataGridTemplateColumn.CellEditingTemplate>
                                <DataTemplate>
                                    <RH:IntTextBox  x:Name="txtbxQty" Style="{StaticResource TextBoxInError}" Text="{Binding Qty,Mode=TwoWay,UpdateSourceTrigger=LostFocus,ValidatesOnDataErrors=True}" lc:FocusAttacher.Focus="True" LostFocus="txtbxQty_LostFocus" PreviewKeyDown="txtbxQty_PreviewKeyDown"></RH:IntTextBox>
                                </DataTemplate>
                            </my:DataGridTemplateColumn.CellEditingTemplate>
                        </my:DataGridTemplateColumn>
                        <!--10-Amount Column-->
                        <my:DataGridTextColumn Header="Amount" Width="100" Binding="{Binding Amount}" IsReadOnly="True" ></my:DataGridTextColumn>

                    </my:DataGrid.Columns>
                </my:DataGrid>

修改

我的课程如下:

 class clsDamagedProducts : INotifyPropertyChanged,IDataErrorInfo
{
    private int _ProductTransactionID;
    private int _ItemID;
    private string _ProductCode;
    private string _ProductName;
    private string _Batch;
    private int _UnitID;
    private string _UnitName;
    private decimal _PurchaseRate;
    private int _AvailableQty;
    private int _Qty;
    private decimal _Amount;
    private string _Remark;

    #region Property Getters and Setters

    public int ProductTransactionID 
    {
        get { return _ProductTransactionID; }
        set
        {
            _ProductTransactionID = value;
            OnPropertyChanged("ProductTransactionID");
        } 
    }

    public int ItemID
    {
        get { return _ItemID; }
        set
        {
            _ItemID = value;
            OnPropertyChanged("ItemID");
        }
    }

    public string ProductCode
    {
        get { return _ProductCode; }
        set
        {
            _ProductCode = value;
            OnPropertyChanged("ProductCode");
        }
    }

    public string ProductName
    {
        get { return _ProductName; }
        set
        {
            _ProductName = value;
            OnPropertyChanged("ProductName");
        }
    }

    public string Batch
    {
        get { return _Batch; }
        set
        {
            _Batch = value;
            OnPropertyChanged("Batch");
        }
    }

    public int UnitID
    {
        get { return _UnitID; }
        set
        {
            _UnitID = value;
            OnPropertyChanged("UnitID");
        }
    }

    public string UnitName
    {
        get { return _UnitName; }
        set
        {
            _UnitName = value;
            OnPropertyChanged("UnitName");
        }
    }

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

    public string Remark
    {
        get { return _Remark; }
        set
        {
            _Remark = value;
            OnPropertyChanged("Remark");
        }
    }

    #endregion

    #region IDataErrorInfo Members

    public string Error
    {
        get
        {
            return "";
        }
    }

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

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

                }
            }

            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
}

1 个答案:

答案 0 :(得分:0)

IDataErrorInfo接口公开名为Error的属性。这是包含您在索引器中设置的文本错误消息的属性,您必须将其作为接口的一部分实现。

请注意,此界面一次只会显示一条错误消息,而无需用户自定义。很难给出一个准确的示例,因为您没有告诉我们实现此接口的类的任何细节。但是,它有点像这样:

您的索引器:

public override string this[string propertyName]
{
    if (propertyName = "Name" && Name == string.Empty) return "Please add the name";
    return string.Empty;
}

当界面看到对属性的更改时,它会调用此索引器。如果在此处找到属性的名称并显示错误消息,则该消息将在实现接口的数据类的Error属性中设置。因此,要查看消息,您只需BindError属性:

<TextBlock Text="{Binding Error}" Foreground="Red" />
<TextBlock Text="{Binding Name}" />

(当然,颜色是可选的)。

更新&gt;&gt;&gt;

IDataErrorInfo接口由模型/数据类型类实现。因此,Error属性位于数据类型类中(正如您在 代码中所示),您可以使用与访问其中任何其他属性相同的方式访问它类:

clsDamagedProducts instance = new clsDamagedProducts();
instance.UnitName = "Some Name";
MessageBox.Show(instance.Error);

更新2&gt;&gt;&gt;

有很多方法可以获得这些验证错误。一种方法是简单地将要验证的每个属性名称传递给索引器方法并返回结果:

public string Error
{
    get
    {
        if (this["Name"] != string.Empty) return this["Name"];
        ...
        else if (this["OtherProperty"] != string.Empty) return this["OtherProperty"];
        return string.Empty;
    }
}

您提到了 也可以使用的Validation.Errors属性,但为了做到这一点,您需要设置ValidatesOnDataErrors和/或{{3属性True。有关这些内容的详情,请参阅NotifyOnValidationErrorWPF: Validation made easy with IDataErrorInfo文章。

我个人不希望直接使用这些属性 Error属性。相反,我在我的基类中有一个名为abstract的{​​{1}}集合属性,它在派生类中被重写:

Errors

正如您所看到的......这使我能够一次查看多个错误。