WPF 将相同的 DataContex 分配给多个页面 MVVM

WPF Assigning the Same DataContex to Multiple Pages MVVM

我有一个 Window 有多个框架。每个框架包含一个或多个页面。所有页面都使用相同的 ViewModel。我控制每个Frame的Visibility来操纵UI.

我最近意识到,当我的程序启动时,每个页面都会触发 ViewModel 的同一个构造函数(因此同一个构造函数会触发多次)(构造函数中的一个简单 MessageBox.Show 会触发多个发射时间)。我能理解为什么会这样,但不是我想要的。

此外,我开始相信我在 C# 中操作不同框架时遇到问题的原因是因为我可能创建了新的 "objects" ViewModel??我不确定这是否是正在发生的事情,但我很确定这不是我想要的。

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

每个页面都有以下内容Xaml:

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

我的相框是这样的。我意识到一个框架可以容纳多个页面,但是操纵可见性可以让我获得更好的性能,我不希望每次页面源更改时构造函数都 运行。

<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>

从页面 XAML 中删除以下内容。

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

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

例如在您的页面代码隐藏 class.

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

然后创建一个ActiveJobViewModel实例的公共实例,并为多个页面设置相同的datacontext。

以下创建 ActiveJobViewModel class 的新实例:

<ViewModel:ActiveJobViewModel/>

如果您的所有页面和框架共享相同的视图模型,您只想执行一次 - 在定义框架的 window 中。如果将视图模型定义为 window:

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

...然后您可以处理 FramesLoadCompleted 事件并以编程方式设置其内容的 DataContext

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"];
}

XAML:

<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>

不要忘记从页面中删除 <Page.DataContext> 元素。