将带有数据透视的页面的视图模型分离为单独的视图模型



我正在使用MVVMLight,我已经创建了标准视图和视图模型。在视图中,我放置了Pivot:

<Grid x:Name="LayoutRoot" Background="Transparent">
<controls:Pivot Title="MY APPLICATION">
<local:FirstPivotItem />
<local:SecondPivotItem />
</controls:Pivot>
</Grid>

以下是我的数据透视项目的样子:

<controls:PivotItem x:Class="Pivot.WindowsPhoneControl1"
xmlns:controls="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls"
// standard references and settings
d:DesignHeight="480" d:DesignWidth="480" Header="First One">
<Grid x:Name="LayoutRoot">
</Grid>
</controls:PivotItem>

在后面的代码中

public partial class WindowsPhoneControl1 : PivotItem
{
public WindowsPhoneControl1() {
InitializeComponent();
}
}

我想为这个数据透视项创建视图模型,然后像处理标准视图一样使用它。我将使用

<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<mvvm:EventToCommand Command="{Binding PivotChangedCommand}" PassEventArgsToCommand="True" />
</i:EventTrigger>
</i:Interaction.Triggers>

以处理选择更改事件,并通过Messanger通知适当的视图模型。我不知道如何在PivotItem类中使用视图模型的可能性,该类是从PivotItems继承的,但不是从ViewModelBase继承的,因为我需要。

对单个项使用标准的PivotItem控件,并将用户控件放在每个项中。然后,每个用户控件都可以将其视图模型作为数据上下文。

<Grid x:Name="LayoutRoot"
Background="Transparent">
<controls:Pivot Title="MY APPLICATION">
<controls:PivotItem Header="first">
<local:PivotUserControl1 />
</controls:PivotItem>
<controls:PivotItem Header="second">
<local:PivotUserControl2 />
</controls:PivotItem>
</controls:Pivot>
</Grid>

取决于您是否提前知道数据透视项是什么,或者它们是基于数据动态创建的。根据你到目前为止所写的内容,我认为这是第一篇。

我以前做过的方法是在父视图模型上有许多PivotItem视图模型作为公共属性,每个数据透视对应一个。然后只需将每个数据透视项的dataContext设置为父视图模型上的正确视图模型属性。

通过这种方式,您可以在没有选择更改事件的情况下逃脱。您还可以直接订阅视图模型上的任何事件,因此不一定需要为通信发送消息,因为所有通信都可以通过父视图模型进行。

第二种方法是,如果你事先不确定你将拥有什么数据透视项,那么在父视图模型上有一个PivotItemViewModels集合——每个数据透视项一个,每个都继承自一个公共基类或接口。将该集合绑定到视图模型的ItemSource。

这有点棘手,因为您必须确定要显示什么控件,但如果您将Templates存储在某个位置作为资源,则可以通过转换器来实现:

public class PivotItemToTemplateConverter : IValueConverter
{
#region IValueConverter Members

public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
switch ((int) value)
{
case 1:
return Application.Current.Resources["Control1Template"];
case 2:
return Application.Current.Resources["Control2Template"];
default:
return Application.Current.Resources["Control3Template"];
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return null;
}
#endregion
}

然后,您可以为您的透视项目创建一个透视项目模板,并使用转换器根据值在其中获得正确的控件。在这种情况下,假设共享的基本视图模型有一个属性ViewModelId,它有效地标识了您感兴趣的控件:

<ContentControl 
Content="{Binding}"
ContentTemplate="{Binding ViewModelId,
Converter={StaticResource PivotItemToTemplateConverter }}" />

最新更新