【问题标题】:problem with binding decimal value in wpf datagridwpf datagrid中绑定十进制值的问题
【发布时间】:2025-12-04 07:15:02
【问题描述】:

又一个 wpf 问题。

我有两个采用十进制值的 DataGridTextColumn。出于某种原因,当我添加一个新行(列的初始值为零)时,我必须在这两列中的任何一个中输入我的值两次。我第一次在其中输入一个值并用制表符退出时,该值返回为零。在我第二次输入该值后,它会保留下来。

<DataGridTextColumn Header="Unit Price" EditingElementStyle="{StaticResource CellEditStyle}" Width="SizeToCells" MinWidth="90" Binding="{Binding ItemUnitPrice, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
<DataGridTextColumn Header="Qty" EditingElementStyle="{StaticResource CellEditStyle}" Width="SizeToCells" MinWidth="65" Binding="{Binding ItemQty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />

dg 绑定到我的 vm 中的 observablecollection。我不确定它与它有什么关系,但是我通过创建一个单独的类(用于在用户离开该行时保存数据)向我的 OC 添加了一个 endedit 事件:

public class ObservableProjectExpenseItems : ObservableCollection<ProjectExpenseItemsBO>
{
    protected override void InsertItem(int index, ProjectExpenseItemsBO item)
    {
        base.InsertItem(index, item);
        item.ItemEndEdit += new ProjectExpenseItemsBO.ItemEndEditEventHandler((x) =>
        {
            if (ItemEndEdit != null)
                ItemEndEdit(x);
        });
    }

    public event ProjectExpenseItemsBO.ItemEndEditEventHandler ItemEndEdit;
}

我的业务对象如下所示:

public class ProjectExpenseItemsBO : IDataErrorInfo, IEditableObject
{
    public int RowID { get; set; }
    public int ProjectExpenseID { get; set; }
    public string ItemNumber { get; set; }
    public string ItemDescription { get; set; }
    public decimal ItemUnitPrice { get; set; }
    public decimal ItemQty { get; set; }
    public string SupplierName { get; set; }
    public DateTime CreateDate { get; set; }

    public ProjectExpenseItemsBO()
    {

    }
   // string method
    static bool IsStringMissing(string value)
    {
        return String.IsNullOrEmpty(value) || value.Trim() == String.Empty;
    }

    private bool _isValid = true;
    public bool IsValid 
    {
        get { return _isValid; }
        set { _isValid = value; }
    }

    #region IDataErrorInfo Members

    public string Error
    {
        get
        {
            return this[string.Empty];
        }
    }

    public string this[string propertyName]
    {
        get
        {
            string result = string.Empty;
            if (propertyName == "ProjectExpenseID")
            {
                if (this.ProjectExpenseID == 0)
                    result = "An existing project expense item must be selected!";
            }

            if (propertyName == "ItemNumber")
            {
                if (this.ItemNumber != null)
                {
                    if (IsStringMissing(this.ItemNumber))
                        result = "Item number cannot be empty!";
                    if (this.ItemNumber.Length > 50)
                        result = "Item number cannot be longer than 50 characters!";
                }
            }

            if (propertyName == "ItemDescription")
            {
                if (this.ItemDescription != null)
                {
                    if (this.ItemDescription.Length > 256)
                        result = "Item description cannot be longer than 256 characters!";
                }
            }

            if (propertyName == "ItemUnitPrice")
            {
                if (this.ItemUnitPrice == 0.0M)
                    result = "Item unit price cannot be empty!";
            }

            if (propertyName == "ItemQty")
            {
                if (this.ItemQty == 0.0M)
                    result = "Item quantity cannot be empty!";
            }

            if (propertyName == "SupplierName")
            {
                if (this.SupplierName != null)
                {
                    if (this.SupplierName.Length > 128)
                        result = "Item number cannot be longer than 128 characters!";
                }
            }

            if (result.Length > 0)
                IsValid = false;
            else
                IsValid = true;

            return result;
        }
    }

    #endregion

    #region IEditableObject Members

    public delegate void ItemEndEditEventHandler(IEditableObject sender);

    public event ItemEndEditEventHandler ItemEndEdit;

    public void BeginEdit()
    {
        //throw new NotImplementedException();
    }

    public void CancelEdit()
    {
        //throw new NotImplementedException();
    }

    public void EndEdit()
    {
        if (ItemEndEdit != null)
        {
            ItemEndEdit(this);
        }
    }

    #endregion
}

}

【问题讨论】:

    标签: wpf datagrid binding


    【解决方案1】:

    这在技术上不是一个答案,但我发现问题如下:

            if (propertyName == "ItemQty") 
            { 
                if (this.ItemQty == 0.0M) 
                    result = "Item quantity cannot be empty!"; 
            }
    

    这总是会在新行上失败,因为 dg 列的默认值为零。一旦我摆脱了这个检查,问题就消失了。

    但是,我也遇到了必填字段的问题。验证过程 (IDataError) 在您输入新行时触发。显然,大多数验证都会失败,因为您还没有输入数据。但是,当您输入初始值时,即使它是合法的,该值也会被清除。我不认为这是正确的行为,并且想知道是否有办法在用户离开数据网格行之前关闭初始验证。除此之外,我不确定为什么它会被清除。它仅在输入初始值时发生。一旦您退出并返回,您可以输入一个值,它会保留它,无论是否有效。如果无效,则验证样式将无效列标记为应有的列。

    【讨论】:

      最近更新 更多