我正在使用MVVM并在DataGrid上显示一些项目。我的模型是RecordingInfo,看起来像:
public class RecordingInfo : IDataErrorInfo
{
public RecordingInfo(string fullDirectoryName, string recordingName, int recordingNumber)
{
FullDirectoryName = fullDirectoryName;
RecordingName = recordingName;
RecordingNumber = recordingNumber;
}
public string FullDirectoryName { get; internal set; }
public string RecordingName { get; set; }
public int RecordingNumber { get; internal set; }
public string Error
{
get { throw new NotImplementedException(); }
}
public string this[string propertyName]
{
get {
if (propertyName == "RecordingName")
{
if (this.RecordingName.Length < 2)
return "Recording Name must be at least two characters";
}
return null;
}
}
}
我最终以编程方式收集了这些RecordingInfo。不允许用户对这些做很多事情,但是他/她可以更改记录名称,使其名称为2个字符或更多,并且记录名称必须是唯一的。即不要更改它以匹配另一个RecordingName。我照顾了第一个要求。这是第二个给我悲伤的人。
对于我的ViewModel,我有
public class RecordingListViewModel : ViewModelBase//, IDataErrorInfo
{
private ObservableCollection<RecordingInfo> _recordings = null;
public RecordingListViewModel()
{
}
public ObservableCollection<RecordingInfo> Recordings
{
get
{
return _recordings;
}
}
// more stuff left off for brevity
在我看来,我将集合绑定到DataGrid并具有:
<DataGrid ItemsSource="{Binding Path=Recordings}" AutoGenerateColumns="False" >
<DataGrid.Columns>
<DataGridTextColumn Header="Recording" IsReadOnly="False" EditingElementStyle="{StaticResource CellEditStyle}" ElementStyle="{StaticResource CellNonEditStyle}" Binding="{Binding RecordingName, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" >
</DataGridTextColumn>
...
</DataGrid.Columns>
我检查2个或更多字符的方式效果很好。但这并不适用于检查用户是否尝试为现有名称提供录音。据推测,我需要以某种方式在ViewModel层处理此问题,因为ViewModel知道所有录制内容。我试着让我的ViewModel派生自IDataErrorInfo但是属性索引器永远不会被调用,这是有意义的,因为它是Observable集合,因此是绑定的单个RecordingInfos。我也想过用“失去的焦点”#34;做一些事情。事件,但DataGridTextColumn似乎没有。我认为这是一个有点常见的问题:验证必须考虑集合项目之间的关系。
顺便说一下,我没有与IDataErrorInfo结合,我也不反对架构中的其他变化。如果我能提供更多详细信息,请通知我。我试图提供最少量的代码。显然,这是一个更大的项目的一部分。任何建议都表示赞赏。
谢谢,
戴夫
答案 0 :(得分:0)
我会做以下事情 1)使RecordingInfo实现INotifyPropertyChanged 2)使用BindingList&lt;&gt;而不是ObservableCollection&lt;&gt;
在viewmodel中,订阅BindingList.ListChanged事件。添加和删除项目时,以及RecordingInfo上的顶级属性更改时,将触发此事件。如果要更改属性,ListChangedEventArgs.PropertyDescriptor属性将包含属性的名称,如果要仅对该属性运行验证(但要小心,当添加/删除项时,这可以为null)。您需要使用ListChangedType属性来确定事件的原因(例如:重置意味着所有更改,ItemAdded表示项目已添加,但ItemChanged表示属性已更改为现有项目。
答案 1 :(得分:0)
您可以让父ViewModel(包含并创建您的RecordingInfos)在其构造函数中传递名称验证Func,以便在验证其名称更改时调用它们。