终于发现一个有趣的新知识了。
本例的核心是RegionContext,意思是一个区域的上下文。但与DataContext似乎并不相同。
先看一下整体思路。
在主窗体上只有一个Region:
<Grid> <ContentControl prism:RegionManager.RegionName="ContentRegion" /> </Grid>
然后在此区域上注册一个视图,但视图中多了一个子区域
<Grid x:Name="LayoutRoot" Background="White" Margin="10"> <Grid.RowDefinitions> <RowDefinition Height="100"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <ListBox x:Name="_listOfPeople" ItemsSource="{Binding People}" DisplayMemberPath="FirstName"/> <ContentControl Grid.Row="1" Margin="10" prism:RegionManager.RegionName="PersonDetailsRegion" prism:RegionManager.RegionContext="{Binding SelectedItem, ElementName=_listOfPeople}"/> </Grid>
这个结构很清楚,上部是一个列表,下面插入一个区域,用来显示选中项的细节。为了体现更多信息,我把lisbox的显示信息改了下,只显示FirstName。
但是定义了一个RegionContext,绑定到SelectedItem。如果这是上下文,这个子视图还有自己的ViewModel怎么办呢?
public class PersonDetailViewModel : BindableBase { private Person _selectedPerson; public Person SelectedPerson { get { return _selectedPerson; } set { SetProperty(ref _selectedPerson, value); } } public PersonDetailViewModel() { } }
系统决定了View 和ViewModel的自动绑定了,Detail绑定的是SelectedPerson,需要实现一个转换。
这个转换在View的后台代码是实现了:
public partial class PersonDetail : UserControl { public PersonDetail() { InitializeComponent(); RegionContext.GetObservableContext(this).PropertyChanged += PersonDetail_PropertyChanged; } private void PersonDetail_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) { var context = (ObservableObject<object>)sender; var selectedPerson = (Person)context.Value; ((PersonDetailViewModel) DataContext).SelectedPerson = selectedPerson; }
这段代码的意思是,Detail 绑定了SelectedItem,如果SelectedItem发生了变化,就变化了的值更新ViewModel