c# – 对于WPF 4.5 DataGrids,INotifyDataErrorInfo是否已损坏
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了c# – 对于WPF 4.5 DataGrids,INotifyDataErrorInfo是否已损坏,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含6337字,纯文字阅读大概需要10分钟。
内容图文
![c# – 对于WPF 4.5 DataGrids,INotifyDataErrorInfo是否已损坏](/upload/InfoBanner/zyjiaocheng/815/366a818f3150458e96a889d45bac067e.jpg)
我在WPF 4.5项目中做了一个简单的INotifyDataErrorInfo实现.这是WPF的新界面,但已在Silverlight中使用了一段时间.
我知道NET4.5仍然被认为是alpha,但我正在尝试解决它是我的代码还是错误的框架.
接口按预期工作,但在将对象绑定到DataGrid时失败.
我收到的例外是:
System.NullReferenceException was unhandled by user code
Message=Object reference not set to an instance of an object.
Source=PresentationFramework StackTrace:
at MS.Internal.Data.ClrBindingWorker.OnDataErrorsChanged(INotifyDataErrorInfo
indei, String propName)
at MS.Internal.Data.PropertyPathWorker.OnErrorsChanged(Object sender, DataErrorsChangedEventArgs e)
at System.Windows.WeakEventManager.ListenerList`1.DeliverEvent(Object
sender, EventArgs e, Type managerType)
at System.Windows.WeakEventManager.DeliverEvent(Object sender, EventArgs args)
at System.ComponentModel.ErrorsChangedEventManager.OnErrorsChanged(Object
sender, DataErrorsChangedEventArgs args)
at INotifyDataErrorInfoTest.Person.NotifyErrorsChanged(String property) in INotifyDataErrorInfoTest\Person.cs:line 109
at INotifyDataErrorInfoTest.Person.AddErrorForProperty(String property, String error) in INotifyDataErrorInfoTest\Person.cs:line 122
at INotifyDataErrorInfoTest.Person.Validate(String propertyName) in INotifyDataErrorInfoTest\Person.cs:line 150
at INotifyDataErrorInfoTest.Person.set_FirstName(String value) in INotifyDataErrorInfoTest\Person.cs:line 18
代码在http://dl.dropbox.com/u/14740106/INotifyDataErrorInfoTest.zip以下或项目中
如果共识是这是一个错误,那么我将发布到MS Connect.
测试:
有两个文本框绑定到Person对象的单个实例.将第一个文本框设置为具有值的James,它将无法通过验证并显示红色框.如果将网格中任何用户的名字设置为James,则会抛出异常.
PS:我知道它不是MVVM,但它只是为了证明或反驳问题.
public class Person : INotifyDataErrorInfo, INotifyPropertyChanged
{
string _firstName;
public string FirstName
{
get { return _firstName; }
set
{
_firstName = value;
Validate("FirstName");
OnPropertyChanged("FirstName");
}
}
string _lastName;
public string LastName
{
get { return _lastName; }
set
{
_lastName = value;
Validate("LastName");
OnPropertyChanged("LastName");
}
}
public Person()
{
}
public Person(string first, string last)
{
this._firstName = first;
this._lastName = last;
}
#region INotifyPropertyChanged Members
/// <summary>
/// Event to indicate that a property has changed.
/// </summary>
[field: NonSerialized]
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Called when a property is changed
/// </summary>
/// <param name="propertyName">The name of the property that has changed.</param>
protected virtual void OnPropertyChanged(string propertyName)
{
OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
}
/// <summary>
/// Called when a property is changed
/// </summary>
/// <param name="e">PropertyChangedEventArgs</param>
protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
{
//Validate the property
Validate(e.PropertyName);
if (null != PropertyChanged)
{
PropertyChanged(this, e);
}
}
#endregion
#region INotifyDataErrorInfo Members
public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
private Dictionary<string, List<string>> _errors = new Dictionary<string, List<string>>();
public IEnumerable GetErrors(string propertyName)
{
if (string.IsNullOrEmpty(propertyName))
{
return (_errors.Values);
}
MakeOrCreatePropertyErrorList(propertyName);
return _errors[propertyName];
}
public bool HasErrors
{
get
{
return (_errors.Where(c => c.Value.Count > 0).Count() > 0);
}
}
void NotifyErrorsChanged(string property)
{
if (ErrorsChanged != null)
{
ErrorsChanged(this, new DataErrorsChangedEventArgs(property));
}
}
public void ClearErrorFromProperty(string property)
{
MakeOrCreatePropertyErrorList(property);
_errors[property].Clear();
NotifyErrorsChanged(property);
}
public void AddErrorForProperty(string property, string error)
{
MakeOrCreatePropertyErrorList(property);
_errors[property].Add(error);
NotifyErrorsChanged(property);
}
void MakeOrCreatePropertyErrorList(string propertyName)
{
if (!_errors.ContainsKey(propertyName))
{
_errors[propertyName] = new List<string>();
}
}
#endregion
/// <summary>
/// Force the object to validate itself using the assigned business rules.
/// </summary>
/// <param name="propertyName">Name of the property to validate.</param>
public void Validate(string propertyName)
{
if (string.IsNullOrEmpty(propertyName))
{
return;
}
if (propertyName == "FirstName")
{
if (FirstName == "James")
{
AddErrorForProperty(propertyName, "FirstName can't be James");
}
else
{
ClearErrorFromProperty(propertyName);
}
}
}
}
public class NameList : ObservableCollection<Person>
{
public NameList()
: base()
{
Add(new Person("Willa", "Cather"));
Add(new Person("Isak", "Dinesen"));
Add(new Person("Victor", "Hugo"));
Add(new Person("Jules", "Verne"));
}
}
public partial class MainWindow : Window
{
Person _person = new Person();
public MainWindow()
{
InitializeComponent();
DataContext = this;
}
public Person Person
{
get { return _person; }
}
}
<Window x:Class="INotifyDataErrorInfoTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:c="clr-namespace:INotifyDataErrorInfoTest"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<c:NameList x:Key="NameListData"/>
</Window.Resources>
<StackPanel>
<StackPanel.Resources>
<Style TargetType="TextBox">
<Setter Property="Margin" Value="5"></Setter>
</Style>
</StackPanel.Resources>
<TextBox Text="{Binding Person.FirstName, Mode=TwoWay, ValidatesOnNotifyDataErrors=True}"/>
<TextBox Text="{Binding Person.LastName, Mode=TwoWay, ValidatesOnNotifyDataErrors=True}"/>
<TextBlock>To generate an error, set the FirstName of any row to James.
</TextBlock>
<DataGrid ItemsSource="{Binding Source={StaticResource NameListData}}" AutoGenerateColumns="True"></DataGrid>
</StackPanel>
</Window>
解决方法:
答案是肯定的.我打开了一个ticket with Microsoft,他们已经确认代码很好,这是.NET 4.5 DataGrid的一个错误.
This is our bug, not yours. When you edit a DataGrid cell, the DataGrid discards bindings for the “display” template and replaces them with bindings for the “edit” template. The discarded bindings should stop listening to the INDEI.ErrorsChanged event. They don’t (that’s the bug), but they are not prepared to get the event any more. When the event arrives, a null-reference crash occurs.
This will be fixed in the final release. Thanks for finding and reporting it.
非常大的bug必须等到最终版本.我们希望它能在下一个版本中得到解决.
内容总结
以上是互联网集市为您收集整理的c# – 对于WPF 4.5 DataGrids,INotifyDataErrorInfo是否已损坏全部内容,希望文章能够帮你解决c# – 对于WPF 4.5 DataGrids,INotifyDataErrorInfo是否已损坏所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。