我的MainView.xaml包含我的SmartForm视图:
<Grid Margin="10">
<views:SmartForm/>
</Grid>
Run Code Online (Sandbox Code Playgroud)
SmartForm视图加载ItemsControl
<Grid Margin="10">
<ItemsControl
ItemsSource="{Binding DataTypeViews}"/>
</Grid>
Run Code Online (Sandbox Code Playgroud)
这是DataTypeViews的ObservableCollection:
List<FormField> formFields = new List<FormField>();
formFields.Add(new FormField { IdCode = "firstName", Label = "First Name", Value = "Jim" });
formFields.Add(new FormField { IdCode = "lastName", Label = "Last Name", Value = "Smith" });
formFields.Add(new FormField { IdCode = "address1", Label = "Address 1", Value = "123 North Ashton Rd." });
formFields.Add(new FormField { IdCode = "address2", Label = "Address 2", Value = "Box 23434" });
formFields.Add(new FormField { IdCode = "city", Label = "City", Value = "New Haven" });
formFields.Add(new FormField { IdCode = "state", Label = "State", Value = "NM" });
formFields.Add(new FormField { IdCode = "zip", Label = "Zip Code", Value = "34234" });
foreach (FormField formField in formFields)
{
DataTypeView dtv = new DataTypeView();
DataTypeViewModel dtvm = new DataTypeViewModel(formField);
dtv.DataContext = dtvm;
DataTypeViews.Add(dtv);
}
Run Code Online (Sandbox Code Playgroud)
每个视图显示构建表单的标签和文本框:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="90"/>
<ColumnDefinition Width="400"/>
</Grid.ColumnDefinitions>
<StackPanel Orientation="Horizontal" Grid.Column="0">
<TextBlock Text="{Binding Label}" FontSize="14"/>
<TextBlock Text=": " FontSize="14"/>
</StackPanel>
<TextBox Grid.Column="1" Text="{Binding Value}" FontSize="12"/>
</Grid>
Run Code Online (Sandbox Code Playgroud)
如何将DataTypeViewModel中发生的文本框更改冒泡到SmartFormViewModel中?
或者换句话说:如果ViewModel A包含ViewModel B的集合,并且在ViewModel B中发生了更改,那么如何将该更改冒泡到ViewModel A?
我认为你应该使用你可以在这里阅读的中介模式.
基本上它是一个静态类,它允许ViewModels(或任何类)相互通信并来回传递参数.
基本上,ViewModel A开始监听某种消息类型(例如ViewModelBChanged),并且每当该事件发生时ViewModelB只是通知任何正在收听此消息类型的人,它也可以传递它想要的任何信息.
这是调解员的骨架.
public static class MyMediator
{
public static void Register(Action<object> callback, string message);
public static void NotifyColleagues(string message, object args);
}
Run Code Online (Sandbox Code Playgroud)
ViewModel A会这样做(可能在构造函数中):
MyMediator.Register(ProcessMessage,"ViewModelBChanged")
Run Code Online (Sandbox Code Playgroud)
然后必须声明一个这样的函数:
void ProcessMessage(object args)
{
//Do some important stuff here
}
Run Code Online (Sandbox Code Playgroud)
只要想要告诉ViewModel A,ViewModel B就会调用它
MyMediator.NotifyColleagues("ViewModelBChanged",this);
Run Code Online (Sandbox Code Playgroud)
中介类将负责调用viewModel A的回调函数.然后每个人都很高兴.
就个人而言,我喜欢将这些字符串消息值放在这样的静态类中
static class MediatorMessages
{
public static string ViewModelBChanged= "ViewModelBChanged";
}
Run Code Online (Sandbox Code Playgroud)
这样你就可以做到以下(而不是上面的):
MyMediator.Register(ProcessMessage,MediatorMessages.ViewModelBChanged)
MyMediator.NotifyColleagues(MediatorMessages.ViewModelBChanged,this);
Run Code Online (Sandbox Code Playgroud)
如果这还不清楚只是谷歌MVVM中介并点击你的心脏内容:)
您可以让父虚拟机连接到子虚拟机上的PropertyChanged事件.这是一种PITA,用于跟踪已添加/删除的子项等等,因此您可以考虑将您的子VM存储在我的ItemObservableCollection:
public sealed class ItemObservableCollection<T> : ObservableCollection<T>
where T : INotifyPropertyChanged
{
public event EventHandler<ItemPropertyChangedEventArgs<T>> ItemPropertyChanged;
protected override void InsertItem(int index, T item)
{
base.InsertItem(index, item);
item.PropertyChanged += item_PropertyChanged;
}
protected override void RemoveItem(int index)
{
var item= this[index];
base.RemoveItem(index);
item.PropertyChanged -= item_PropertyChanged;
}
protected override void ClearItems()
{
foreach (var item in this)
{
item.PropertyChanged -= item_PropertyChanged;
}
base.ClearItems();
}
protected override void SetItem(int index, T item)
{
var oldItem = this[index];
oldItem.PropertyChanged -= item_PropertyChanged;
base.SetItem(index, item);
item.PropertyChanged -= item_PropertyChanged;
}
private void item_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
OnItemPropertyChanged((T)sender, e.PropertyName);
}
private void OnItemPropertyChanged(T item, string propertyName)
{
ItemPropertyChanged.Raise(this, new ItemPropertyChangedEventArgs<T>(item, propertyName));
}
}
Run Code Online (Sandbox Code Playgroud)
然后,您的父虚拟机可以通过以下方式监听子项的所有更改:
_formFields.ItemPropertyChanged += (s, e) => Foo();
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4303 次 |
| 最近记录: |