我有一个ViewModels列表,每个ViewModels都包含一个列表。
我想将这个列表绑定到视图中的ListBox,这样我就可以设置一个SelectedViewModel
,并且视图中的ListBox现在显示新的SelectedViewModel
中的条目。这也应该保留选择。
是否有可能使用当前的Caliburn Micro约定或我必须明确说明这一点?
例如:我有一个名为vmList
的ViewModels列表,其中包含两个ViewModels, Fruit
和Veg
。
ViewModel Fruit
包含列表["Apple", "Pear"]
。
ViewModel Veg
包含列表["Carrot", "Cabbage"]
。
Fruit
是当前的SelectedViewModel
,所以我的视图的列表框当前应该显示:
Apple
*Pear*
Pear
是当前列表框中被选中的项。
现在我将Veg
设置为SelectedViewModel
,我的视图更新为显示:
*Carrot*
Cabbage
Carrot
是当前列表框中选中的项。现在,如果我将Fruit
设置回SelectedViewModel
,我的视图应该更新为显示:
Apple
*Pear*
其中Pear
仍然是ListBox中的选中项
这应该是可能的——最简单的功能是使用CMs约定绑定列表内容,并为列表提供SelectedItem
绑定。因为你想在每个VM中跟踪最后选择的项目,你也需要保持标签(无论是在VM本身还是在主VM中)
所以解决方案可以是:
public class ViewModelThatHostsTheListViewModel
{
// All these properties should have property changed notification, I'm just leaving it out for the example
public PropertyChangedBase SelectedViewModel { get; set; }
public object SelectedItem { get; set; }
// Dictionary to hold last selected item for each VM - you might actually want to track this in the child VMs but this is just one way to do it
public Dictionary<PropertyChangedBase, object> _lastSelectedItem = new Dictionary..etc()
// Keep the dictionary of last selected item up to date when the selected item changes
public override void NotifyOfPropertyChange(string propertyName)
{
if(propertyName == "SelectedItem")
{
if(_lastSelectedItem.ContainsKey(SelectedViewModel))
_lastSelectedItem[SelectedViewModel] = SelectedItem;
else
_lastSelectedItem.Add(SelectedViewModel, SelectedItem);
}
}
}
然后在XAML
中<ListBox x:Name="SelectedViewModel" SelectedItem="{Binding SelectedItem, Mode=TwoWay}" />
显然,在这里设置你的项目模板来绑定到视图模型上的一个公共属性(比如DisplayName
使用IHaveDisplayName
接口来保持东西的美观和集成)
只是一个快速提示:如果你的vm本身不是List
对象,而是包含一个列表,那么你可能必须将列表项显式绑定到ListBox
,但这取决于你的ItemTemplate
(你可以让CM根据ContentControl
约定绑定继续解析vm和vm的视图)
<ListBox ItemsSource="{Binding SelectedViewModel.ListItems}" ...etc />