我正在使用Prism MVVM框架开发WPF应用程序。而且我不知道如何在父视图模型和子视图模型之间正确传递数据。
我有2个视图模型 - ParentViewModel和内部ChildViewModel。
public class ParentViewModel
{
public ParentViewModel
{
ChildViewModel = new ChildViewModel(params);
}
private ChildViewModel _childViewModel;
public ChildViewModel ChildViewModel
{
get { return _childViewModel; }
set
{
SetProperty(ref _childViewModel, value);
}
}
//This is does not work
public int SelectedChildNumber
{
return _childViewModel.SelectedNumber;
}
}
public class ChildViewModel
{
public ChildViewModel
{
_numbers = new List<int>();
}
private List<int> _numbers;
public List<int> Numbers
{
get { return _numbers; }
set
{
SetProperty(ref _numbers, value);
}
}
private int _selectedNumber;
public int SelectedNumber
{
get { return _selectedNumber; }
set
{
SetProperty(ref _selectedNumber, value);
}
}
}
我想从子视图模型中获取并使用选定的值。我的方法不起作用 - 如果SelectedNumber在ChildViewModel中发生更改,SelectedChildNumber不想刷新。
更新 好的,如果我在ParentViewModel中有ChildViewModel集合怎么办?其中一个ChildViewModels的属性IsSelected等于true。如何从集合中获取这个选定的视图模型?
public class ParentViewModel
{
public ParentViewModel
{
Items = GetItems();
}
private ObservableCollection<ChildViewModel> _items;
public ObservableCollection<ChildViewModel> Items
{
get
{
return _items;
}
set
{
SetProperty(ref _items, value);
}
}
}
public class ChildViewModel
{
public ChildViewModel
{
}
private bool _isSelected;
public bool IsSelected
{
get { return _isSelected; }
set
{
SetProperty(ref _isSelected, value);
}
}
}
如何获取选定的视图模型?也许使用转换器?
<someUserControl DataContext="{Binding ParentViewModel.Items, Converter={x:Static c:GetSelectedItemConverter.Instance}}" />
在转换器中我可以找到所选项目。或者这是个坏主意?
更新2:
好的,我在Ed Plunkett的帮助下击败了这个问题。最终版本应为:
public class ParentViewModel
{
public ParentViewModel
{
Items = GetItems();
foreach (var item in Items)
{
item.PropertyChanged += ChildViewModel_PropertyChanged;
}
}
private ObservableCollection<ChildViewModel> _items;
public ObservableCollection<ChildViewModel> Items
{
get
{
return _items;
}
set
{
SetProperty(ref _items, value);
}
}
private ChildViewModel _selectedChild;
public ChildViewModel SelectedChild
{
get { return _selectedChild; }
set
{
SetProperty(ref _selectedChild, value);
}
}
private void ChildViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
var child = (ChildViewModel)sender;
if (e.PropertyName == nameof(ChildViewModel.IsSelected) && child.IsSelected)
{
SelectedChild = child;
}
}
}
答案 0 :(得分:1)
直接绑定到子属性:
<ListBox
ItemsSource="{Binding ChildViewModel.Numbers}"
SelectedItem="{Binding ChildViewModel.SelectedNumber}"
/>
<Label Content="{Binding ChildViewModel.SelectedNumber}" />
这是绑定路径中父级ChildViewModel
属性的名称,而不是类型。 Binding
现在知道收听有关ChildViewModel
和PropertyChanged
的{{1}}通知的SelectedNumber
对象。
您的版本不起作用的原因是,当Numbers
更改时,父级不会引发PropertyChanged
。事实上,父母不知道它何时发生变化比UI更多。父可以处理孩子的SelectedChildNumber
事件,有时候已完成。
PropertyChanged
但是你不需要像这样的情况那样做。
public ParentViewModel()
{
ChildViewModel = new ChildViewModel(params);
// Handle child's PropertyChanged event
ChildViewModel.PropertyChanged += ChildViewModel_PropertyChanged;
}
private void ChildViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
var child = (ChildViewModel)sender;
if (e.PropertyName == nameof(ChildViewModel.SelectedNumber))
{
// Do stuff
}
}
应该是ChildViewModel.Numbers
,而不是ObservableCollection<int>
。这样,如果您向其添加更多数字或删除任何数字,该集合将自动通知UI,List<int>
将自动相应地更新自身。