C# 如何在WPF中使用ValidateSondaErrors绑定空文本框时防止UI冻结?

C# 如何在WPF中使用ValidateSondaErrors绑定空文本框时防止UI冻结?,c#,wpf,code-behind,C#,Wpf,Code Behind,由@Bijington在评论中回答,见更新2 当我开始将鼠标悬停在一个绑定到对象属性的空文本框上时,UI冻结在我身上有点麻烦。 我无法再与我的应用程序交互,CPU使用率从大约5%上升到50%以上。只有当我将ValidatesOnDaerRors设置为true并且文本框开始标记为无效(这是故意的)时,才会发生这种情况 以下是一些可能相关的短端代码: 提供数据的对象 public class Product : Item { public string Name {

由@Bijington在评论中回答,见更新2

当我开始将鼠标悬停在一个绑定到对象属性的空文本框上时,UI冻结在我身上有点麻烦。 我无法再与我的应用程序交互,CPU使用率从大约5%上升到50%以上。只有当我将ValidatesOnDaerRors设置为true并且文本框开始标记为无效(这是故意的)时,才会发生这种情况

以下是一些可能相关的短端代码:

提供数据的对象

public class Product : Item
{
    public string Name
    {
        get
        {
            return row.Field<string>("name");
        }
        set
        {
            row.SetField<string>("name", value);
            OnPropertyChanged("Name");
        }
    }

    public override SelectTables Table
    {
        get
        {
            return classToSelectTables<Product>();
        }
    }

    public override object[] ItemFields
    {
        get
        {
            return row.ItemArray;
        }
        set
        {
            row.ItemArray = value;
            OnPropertyChanged("ItemFields");
            OnPropertyChanged("Name");
        }
    }

    public override string this[string columnName]
    {
        get
        {
            string errorMessage = string.Empty;
            switch (columnName)
            {
                case "Name":
                    if (string.IsNullOrWhiteSpace(Name))
                    {
                        errorMessage = "Der Name muss zwischen " + MinLenght + " und " + MaxLenght + " Zeichen lang sein.";
                    }
                    break;
                default:
                    break;
            }
            Debug.WriteLine("Errorcheck " + errorMessage);
            return errorMessage;
        }
    }

    public Product() : base() { }

    public Product(ref DataRow row) : base(ref row) { }
}
公共类产品:项目
{
公共字符串名
{
得到
{
返回行。字段(“名称”);
}
设置
{
行设置字段(“名称”,值);
不动产变更(“名称”);
}
}
公共覆盖SelectTables表
{
得到
{
返回classtoselectables();
}
}
公共覆盖对象[]项字段
{
得到
{
返回row.ItemArray;
}
设置
{
row.ItemArray=值;
OnPropertyChanged(“项目字段”);
不动产变更(“名称”);
}
}
公共重写字符串此[string columnName]
{
得到
{
string errorMessage=string.Empty;
开关(列名称)
{
案例“名称”:
if(string.IsNullOrWhiteSpace(Name))
{
errorMessage=“名称muss zwischen”+MinLenght+“und”+MaxLenght+“Zeichen lang sein.”;
}
打破
违约:
打破
}
Debug.WriteLine(“Errorcheck”+errorMessage);
返回错误消息;
}
}
公共产品():base(){}
公共产品(参考数据行):基本(参考行){}
}
执行绑定的类

class ItemBinding<T> where T : Item
{
    private ItemViewModel<T> viewModel;
    public ItemViewModel<T> ViewModel
    {
        get
        {
            return viewModel;
        }
    }

    private string CurrencyFormat
    {
        get
        {
            return "C";
        }
    }

    public ItemBinding()
    {
        viewModel = (ItemViewModel<T>)getViewModel(Item.classToSelectTables<T>());
    }

    private Binding getBinding(PropertyPath path, string format = null)
    {
        Binding binding = new Binding();
        binding.Path = path;
        binding.Source = viewModel.Temporary;
        binding.ValidatesOnDataErrors = true;
        binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
        if (format != null)
        {
            binding.ConverterCulture = CultureInfo.CurrentCulture;
            binding.StringFormat = format;
        }
        return binding;
    }

    public void doDefaultBinding(TextBox text, PropertyPath path)
    {
        BindingOperations.SetBinding(text, TextBox.TextProperty, getBinding(path));
    }
}
类ItemBinding,其中T:Item
{
私有项目视图模型;
公共项目视图模型视图模型
{
得到
{
返回视图模型;
}
}
专用字符串格式
{
得到
{
返回“C”;
}
}
公共项绑定()
{
viewModel=(ItemViewModel)getViewModel(Item.classToSelectTables());
}
私有绑定getBinding(PropertyPath路径,字符串格式=null)
{
绑定=新绑定();
binding.Path=Path;
binding.Source=viewModel.Temporary;
binding.validateSondaerRors=true;
binding.UpdateSourceTrigger=UpdateSourceTrigger.PropertyChanged;
if(格式!=null)
{
binding.ConverterCulture=CultureInfo.CurrentCulture;
binding.StringFormat=格式;
}
返回绑定;
}
公共void doDefaultBinding(文本框文本,属性路径)
{
BindingOperations.SetBinding(text,TextBox.TextProperty,getBinding(path));
}
}
更新:

下面是基类项

    public abstract class Item : INotifyPropertyChanged, IDataErrorInfo
{
    protected DataRow row;

    public abstract object[] ItemFields { get; set; }


    public long? Id
    {
        get
        {
            return row.Field<long?>("id");
        }
    }

    public abstract SelectTables Table { get; }

    public string Error
    {
        get
        {
            return string.Empty;
        }
    }

    public abstract string this[string columnName]
    {
        get;
    }

    public Item()
    {
        Debug.WriteLine("new " + typeof(Item).ToString());
        if (row != null)
        {
            return;
        }
        row = Tables[(int)Table].NewRow();
    }

    public Item(ref DataRow row) : this()
    {
        this.row = row;
    }

    public DataRow getCopyOfRow()
    {
        DataRow row = Tables[(int)Table].NewRow();
        row.ItemArray = (object[])this.row.ItemArray.Clone();
        return row;
    }

    public static SelectTables classToSelectTables<T>()
    {
        Type t = typeof(T);
        return DatabaseManager.getTable(t.Name);
    }

    public void add()
    {
        Tables[(int)Table].Rows.Add(row);
    }

    public void delete()
    {
        if (row == null)
        {
            return;
        }
        row.Delete();
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            Debug.WriteLine("PropertyChanged");
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
公共抽象类项:INotifyPropertyChanged,IDataErrorInfo
{
受保护的数据行;
公共抽象对象[]项字段{get;set;}
公共长Id
{
得到
{
返回行字段(“id”);
}
}
公共抽象SelectTables表{get;}
公共字符串错误
{
得到
{
返回字符串。空;
}
}
公共抽象字符串此[string columnName]
{
得到;
}
公共项目()
{
Debug.WriteLine(“new”+typeof(Item).ToString());
如果(行!=null)
{
返回;
}
行=表[(int)表].NewRow();
}
公共项(参考数据行):此()
{
this.row=行;
}
公共数据行getCopyOfRow()
{
数据行行=表[(int)Table].NewRow();
row.ItemArray=(对象[])this.row.ItemArray.Clone();
返回行;
}
公共静态SelectTables类到SelectTables()
{
类型t=类型(t);
返回DatabaseManager.getTable(t.Name);
}
公共无效添加()
{
表[(int)Table].Rows.Add(row);
}
公共作废删除()
{
if(行==null)
{
返回;
}
行。删除();
}
公共事件属性更改事件处理程序属性更改;
公共void OnPropertyChanged(字符串propertyName)
{
if(PropertyChanged!=null)
{
Debug.WriteLine(“PropertyChanged”);
PropertyChanged(这是新的PropertyChangedEventArgs(propertyName));
}
}
}
更新2 原来我是个白痴。我忘了在文本框样式中为工具提示设置路径。现在它可以工作了:

            <Style.Triggers>
            <Trigger Property="Validation.HasError" Value="true">
                <Setter Property="ToolTip" Value="{Binding Path=(Validation.Errors)[0].ErrorContent, RelativeSource={x:Static RelativeSource.Self}}"/>
            </Trigger>
        </Style.Triggers>


你的
IDataErrorInfo
INotifyDataErrorInfo
info实现在基类“Item”中的哪个位置?@bikington。对不起,我以为我浏览了整个部分。您是否在输出窗口中看到任何绑定错误?@Bijington否没有绑定错误。我甚至可以使用此绑定成功地添加和编辑产品,只要我在文本框为空时不将鼠标悬停在文本框上。是否为文本框使用自定义样式?听起来好像是试图填充工具提示的过程导致了问题,我认为基本样式中的问题应该只是您的错误消息。