C# 如何在WPF中使用ValidateSondaErrors绑定空文本框时防止UI冻结?
由@Bijington在评论中回答,见更新2 当我开始将鼠标悬停在一个绑定到对象属性的空文本框上时,UI冻结在我身上有点麻烦。 我无法再与我的应用程序交互,CPU使用率从大约5%上升到50%以上。只有当我将ValidatesOnDaerRors设置为true并且文本框开始标记为无效(这是故意的)时,才会发生这种情况 以下是一些可能相关的短端代码: 提供数据的对象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 {
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否没有绑定错误。我甚至可以使用此绑定成功地添加和编辑产品,只要我在文本框为空时不将鼠标悬停在文本框上。是否为文本框使用自定义样式?听起来好像是试图填充工具提示的过程导致了问题,我认为基本样式中的问题应该只是您的错误消息。