我在ListView
(like this)中有一个由EditableTextblock
组成的DataTemplate
的MVVM应用。
这是我的模特:
public class MyModel
{
private string _data;
public string Data
{
get { return _data; }
set { _data = value; }
}
}
我的viewmodel公开ObservableCollection
MyModel
:
public class MyViewModel
{
[...]
public ObservableCollection<Mymodel> models = new ObservableCollection<MyModel>();
}
并且在视图中绑定到ListView
:
<ListView ItemsSource={Binding models}>
<!-- code removed for more visibility -->
<DataTemplate>
<controls:EditableTextblock Text="{Binding Data, Mode=TwoWay}" />
</DataTemplate>
<!-- ... -->
</ListView>
您是否有任何线索,当我在列表中的项目中更新数据成员的值时,会检查集合中是否已存在值?
例如,如果我将字段更新为&#34;值1&#34;,它会检查模型集合中是否存在已具有此值的成员数据。
如果它找到一个,它会增加例如&#34; 0&#34;在成员数据的末尾。
答案 0 :(得分:1)
对于这样的事情,我通常将我的模型包装在他们自己的视图模型类中,并在那里添加验证。包装器将原始模型的实例包装起来,再加上对父视图模型的引用,以便它可以检查重复项或对父项执行其他操作。
如果您使用某种消息系统(如MVVMLight的Messenger
类来在视图模型之间进行通信),也可以在不引用父级的情况下完成验证。
我用这种方式包装它们的主要原因是因为我喜欢保持模型“纯粹”,而不需要任何更改通知,WPF或业务逻辑,超出了域的直接要求。这允许我将模型保持为简单的数据类,并将任何业务或视图特定的逻辑移动到更合适的位置。
您现有的类(注意,我将集合更改为包装类):
public class MyViewModel : BaseViewModel //whatever base class you use to notify of property changes.
{
[...]
public ObservableCollection<MyModelVm> models = new ObservableCollection<MyModelVm>();
}
public class MyModel
{
private string _data;
public string Data
{
get { return _data; }
set { _data = value; }
}
}
新的包装器视图模型:
public class MyModelVm : BaseViewModel //whatever base class you use to notify of property changes.
{
public MyModelVm(MyModel model, MyViewModel parentViewModel)
{
Model = model;
ParentViewModel = parentViewModel;
}
public MyModel Model { get; }
public MyViewModel ParentViewModel { get; }
public string Data
{
get { return Model.Data; }
set
{
if (ParentViewModel.models.Any(x => x != this && x.Data == this.Data))
{
//Duplicate entered
}
else
{
//Not a duplicate, go ahead and allow the change.
Model.Data = value;
//don't forget to notify of property change!
}
}
}
}
答案 1 :(得分:1)
如果MyModel
类实现INotifyPropertyChanged
并在设置PropertyChanged
属性时引发Data
事件,则可以在视图模型中处理:
public class MyViewModel
{
public ObservableCollection<MyModel> models = new ObservableCollection<MyModel>();
public MyViewModel()
{
models.CollectionChanged += Models_CollectionChanged;
}
private void Models_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null)
{
foreach (object model in e.NewItems)
{
(model as INotifyPropertyChanged).PropertyChanged
+= new PropertyChangedEventHandler(Model_PropertyChanged);
}
}
if (e.OldItems != null)
{
foreach (object model in e.OldItems)
{
(model as INotifyPropertyChanged).PropertyChanged
-= new PropertyChangedEventHandler(Model_PropertyChanged);
}
}
}
private void Model_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
MyModel updatedModel = sender as MyModel;
MyModel duplicate = models.FirstOrDefault(x => x != updatedModel && x.Data == updatedModel.Data);
if(duplicate != null)
{
updatedModel.Data += "0";
}
}
}
public class MyModel : INotifyPropertyChanged
{
private string _data;
public string Data
{
get { return _data; }
set { _data = value; NotifyPropertyChanged(); }
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}