WPF将同一DataContex分配给多页MVVM

时间:2018-08-18 21:47:59

标签: wpf mvvm datacontext

我有一个带有多个框架的窗口。每个框架包含一个或多个页面。所有页面使用相同的ViewModel。我控制每个Frame的可见性来操纵UI。

我最近意识到,当我的程序启动时,每个Pages都将触发ViewModel的同一构造函数(因此,同一构造函数将被多次触发)(一个简单的MessageBox.Show构造函数在启动时会多次触发)。 。对于我来说这是为什么会发生,但我想要的不是。

此外,我已经开始相信在C#中处理不同的框架会遇到麻烦的原因是因为我可能创建了ViewModel的新“对象”?我不确定这是否正在发生,但是我很确定这不是我想要的。

有没有一种方法可以设置Pages的DataContext(在Xaml中),以便构造函数仅触发一次,但仍将每个页面的DataContext设置为ViewModel?还是我应该探索另一种方法?我还在学习...

每个页面具有以下Xaml:

<Page.DataContext>
    <ViewModel:ActiveJobViewModel/>
</Page.DataContext>

我的相框看起来像这样。我意识到一个框架可以容纳多个页面,但是操纵可见性可以使我获得更好的性能,并且我不希望每次Page源更改时都运行Constructor。

<Frame Source="ActiveJobPage.xaml" Grid.Row="2" Grid.Column="3" 
       Visibility="{Binding ElementName=ActiveJobPageToggleButton, Path=IsChecked, Converter={StaticResource booleanToVisibility}, UpdateSourceTrigger=PropertyChanged}" 
       Style="{StaticResource FramePage}">
</Frame>

<Frame  Source="CustomerPage.xaml" Grid.Row="2" Grid.Column="3"
        Visibility="{Binding objHomePage_PageVisibility.CustomersPageToggleButtonIsChecked, Converter={StaticResource booleanToVisibility}, UpdateSourceTrigger=PropertyChanged}"
        Style="{StaticResource FramePage}">
</Frame>

2 个答案:

答案 0 :(得分:1)

从Page XAML中删除以下内容。

<Page.DataContext>
    <ViewModel:ActiveJobViewModel/>
</Page.DataContext>

并在代码中手动将两个页面的DataContext设置为相同实例。

例如在您的Page代码隐藏类中。

public void SetDataContext(ActiveJobViewModel commonContext)
{
   this.DataContext = commonContext;
}

然后创建ActiveJobViewModel实例的公共实例,并为多个页面设置相同的数据上下文。

答案 1 :(得分:1)

以下内容创建了ActiveJobViewModel类的新实例:

<ViewModel:ActiveJobViewModel/>

如果所有页面和框架共享相同的视图模型,则只需在定义框架的窗口中执行一次。如果您将视图模型定义为窗口中的资源:

<Window ...>
    <Window.Resources>
        <ViewModel:ActiveJobViewModel x:Key="viewModel"/>
    </Window.Resources>
    <!-- frames ... -->
</Window>

...然后,您可以处理LoadCompleted的{​​{1}}事件并以编程方式设置其内容的Frames

DataContext

XAML:

private void Frame_LoadCompleted(object sender, System.Windows.Navigation.NavigationEventArgs e)
{
    Frame frame = (Frame)sender;
    FrameworkElement content = frame.Content as FrameworkElement;
    if (content != null)
        content.DataContext = Resources["viewModel"];
}

别忘了从页面中删除<Frame Source="ActiveJobPage.xaml" Grid.Row="2" Grid.Column="3" LoadCompleted="Frame_LoadCompleted" Visibility="{Binding ElementName=ActiveJobPageToggleButton, Path=IsChecked, Converter={StaticResource booleanToVisibility}, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource FramePage}"> </Frame> 元素。