gpt4 book ai didi

wpf - UI 未调用 INotifyDataErrorInfo.GetErrors()

转载 作者:行者123 更新时间:2023-12-01 09:56:54 24 4
gpt4 key购买 nike

我有一个实现 INotifyPropertyChanged 的模型和 INotifyDataErrorInfo .每当我修改了属性时,就会触发 Property changed 事件,但由于某种原因,当我引发 Error 事件处理程序时,UI 确实会调用 GetErrors 方法。这会导致验证错误不会呈现到 UI。

有人可以看看我是如何设置 INotifyDataErrorInfo 并告诉我是否做错了什么吗?

基本模型实现

public class BaseChangeNotify : INotifyPropertyChanged, INotifyDataErrorInfo
{
private bool isDirty;

private Dictionary<string, List<string>> errors = new Dictionary<string, List<string>>();

public BaseChangeNotify()
{
}

public event PropertyChangedEventHandler PropertyChanged;

public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;

public bool IsDirty
{
get
{
return this.isDirty;
}

set
{
this.isDirty = value;
this.OnPropertyChanged();
}
}

public bool HasErrors
{
get
{
return this.errors.Count(e => e.GetType() == typeof(ErrorMessage)) > 0;
}
}

public IEnumerable GetErrors(string propertyName)
{
if (string.IsNullOrEmpty(propertyName) ||
!this.errors.ContainsKey(propertyName))
{
return null;
}

return this.errors[propertyName];/*.Where(e => (e is ErrorMessage));*/
}

protected virtual void AddError(string propertyName, string error, bool isWarning = false)
{
if (!this.errors.ContainsKey(propertyName))
{
this.errors[propertyName] = new List<string>();
}

if (!this.errors[propertyName].Contains(error))
{
if (isWarning)
{
this.errors[propertyName].Add(error);
}
else
{
this.errors[propertyName].Insert(0, error);
}

this.OnErrorsChanged(propertyName);
}
}

protected virtual void RemoveError(string propertyName, string error)
{
if (this.errors.ContainsKey(propertyName) &&
this.errors[propertyName].Contains(error))
{
this.errors[propertyName].Remove(error);

if (this.errors[propertyName].Count == 0)
{
this.errors.Remove(propertyName);
}

this.OnErrorsChanged(propertyName);
}
}

public virtual void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
// Perform the IsDirty check so we don't get stuck in a infinite loop.
if (propertyName != "IsDirty")
{
this.IsDirty = true; // Each time a property value is changed, we set the dirty bool.
}

if (this.PropertyChanged != null)
{
// Invoke the event handlers attached by other objects.
try
{
// When unit testing, this will always be null.
if (Application.Current != null)
{
try
{
Application.Current.Dispatcher.Invoke(() =>
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)));

}
catch (Exception)
{

throw;
}
}
else
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
catch (Exception)
{
throw;
}
}
}

/// <summary>
/// Called when an error has changed for this instance.
/// </summary>
/// <param name="propertyName">Name of the property.</param>
public virtual void OnErrorsChanged([CallerMemberName] string propertyName = "")
{
if (string.IsNullOrWhiteSpace(propertyName))
{
return;
}

if (this.ErrorsChanged != null)
{
this.ErrorsChanged(this, new DataErrorsChangedEventArgs(propertyName));
}
}
}

使用实现的模型
public class PayItem : BaseChangeNotify
{
private Section section;

public Section Section
{
get
{
return this.section;
}

set
{
this.section = value;
this.ValidateSection();
this.OnPropertyChanged();
}
}

private void ValidateSection([CallerMemberName] string propertyName = "")
{
const string sectionError = "You must select a Section.";
if (this.Section == null || this.Section.Name.Length > 1)
{
this.AddError(propertyName, sectionError);
}
else
{
this.RemoveError(propertyName, sectionError);
}
}

试图使用它的 View
<ComboBox Name="SectionComboBox"
ItemsSource="{Binding Path=ProjectSections}"
SelectedItem="{Binding Path=SelectedPayItem.Section,
NotifyOnValidationError=True,
UpdateSourceTrigger=PropertyChanged}">

该应用程序是用 WPF 编写的,而 WPF 文档非常稀缺。我已通读 Silverlight documentation就可以了 along with其他一些 blog posts我找到了 on the internet并以博客作者建议的每种不同方式实现。每次结果都一样, GetErrors()方法永远不会被绑定(bind)引擎击中。

谁能看到我做错了什么?当我的模型设置了属性后,我可以单步调试调试器并最终在 OnErrorsChanged 中结束。事件处理程序,并且事件被调用。但是,当它被调用时什么都没有发生,所以我很难过。

提前感谢您的帮助。

乔纳森

编辑

另外我想指出,过去几个月我一直在基类中使用 IDataErrorInfo 没有任何问题。绑定(bind)工作,错误报告给 View ,一切都很开心。当我从 IDataErrorInfo 更改为 INotifyDataErrorInfo 时,验证似乎停止与 View 通信。

最佳答案

引发 ErrorsChanged 事件时,INotifyDataErrorInfo.HasErrors 属性必须返回 true。否则绑定(bind)引擎会忽略错误。您的 HasErrors 属性将始终返回 false。发生这种情况是因为您正在检查 ErrorMessage 类型的项目,但您的字典包含 KeyValuePair > 类型的项目。除此之外,计算所有项目的效率非常低。您应该改用 .Any() 。

顺便说一句,INotifyDataErrorInfo 的 MSDN 文档说如下:

Note that the binding engine never uses the HasErrors property, although you can use it in custom error reporting.



这是完全错误的,我花了几个小时才发现这一点。

关于wpf - UI 未调用 INotifyDataErrorInfo.GetErrors(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24518520/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com