验证一个集合项的验证取决于其他项时,ObservableCollection中的项绑定到DataGrid

时间:2014-03-20 00:53:44

标签: validation data-binding mvvm datagrid observablecollection

我正在使用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结合,我也不反对架构中的其他变化。如果我能提供更多详细信息,请通知我。我试图提供最少量的代码。显然,这是一个更大的项目的一部分。任何建议都表示赞赏。

谢谢,

戴夫

2 个答案:

答案 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,以便在验证其名称更改时调用它们。