如何从 Page 访问 MainWindow 视图模型?

How to get access to the MainWindow viewmodel from Page?

我想了解 WPF 中的绑定系统。在我的示例中,我需要从 XAML.

中的 Page 访问 MainWindow viewmodel

我有一个解决方案来实现它。但我想知道更多不同的方式

MainWindow.xaml

<Window x:Class="FunAnkiWPF.MainWindow"
    ...omitted for brevity
    Height="450" Width="800"
    DataContext="{Binding ViewModel, RelativeSource={RelativeSource 
Self}}">

MainWindow.xaml.cs

public partial class MainWindow : Window
{        
    public MainWindowViewModel ViewModel { get; set; }

    public MainWindow()
    {
        ViewModel = new MainWindowViewModel(this);
        InitializeComponent();            
    }    
}

StartPage.xaml普通页面

StartPage.xaml.cs一个有效的解决方案

public partial class StartPage : Page
{
    public StartPage()
    {
        InitializeComponent();
        DataContext = App.Current.MainWindow.DataContext;
    }
}

如何直接访问 MainWindow ViewModel 属性(在 XAML 和代码隐藏中)? 如何访问 XAML 中的另一个数据上下文(就像在我的 StartPage 代码隐藏中一样)?

从子控件绑定到父 window 数据上下文中的 属性 的简短回答是相对源,例如:

         <TextBlock Text="{Binding Path=DataContext.MainWinVMString, 
          RelativeSource={RelativeSource  AncestorType={x:Type Window}}}"

这里有一个例子,可以让您体会到我的建议。

MainWindow 标记有点快 n 脏。 我会将数据模板放入由 app.xaml.

合并的资源字典中
    Title="MainWindow" Height="350" Width="525">
<Window.Resources>
    <DataTemplate DataType="{x:Type local:LoginViewModel}">
        <local:LoginUC/>
    </DataTemplate>
    <DataTemplate DataType="{x:Type local:UserViewModel}">
        <local:UserUC/>
    </DataTemplate>
</Window.Resources>
<Window.DataContext>
    <local:MainWindowViewModel/>
</Window.DataContext>
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="100"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <ItemsControl ItemsSource="{Binding NavigationViewModelTypes}">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Button Content="{Binding Name}"
                    Command="{Binding DataContext.NavigateCommand, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
                    CommandParameter="{Binding VMType}"
                />
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
    <ContentControl Grid.Column="1"
                    Content="{Binding CurrentViewModel}"
                    />
</Grid>

视图模型:

public class MainWindowViewModel : INotifyPropertyChanged
{
    public string MainWinVMString { get; set; } = "Hello from MainWindoViewModel";

    public ObservableCollection<TypeAndDisplay> NavigationViewModelTypes { get; set; } = new ObservableCollection<TypeAndDisplay>
        (
        new List<TypeAndDisplay>
        {
           new TypeAndDisplay{ Name="Log In", VMType= typeof(LoginViewModel) },
           new TypeAndDisplay{ Name="User", VMType= typeof(UserViewModel) }
        }
        );

    private object currentViewModel;

    public object CurrentViewModel
    {
        get { return currentViewModel; }
        set { currentViewModel = value; RaisePropertyChanged(); }
    }
    private RelayCommand<Type> navigateCommand;
    public RelayCommand<Type> NavigateCommand
    {
        get
        {
            return navigateCommand
              ?? (navigateCommand = new RelayCommand<Type>(
                vmType =>
                {
                    CurrentViewModel = null;
                    CurrentViewModel = Activator.CreateInstance(vmType);
                }));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void RaisePropertyChanged([CallerMemberName] String propertyName = "")
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

Relaycommand 来自 nuget 包 mvvmlightlibs。

用户UC:

<Grid Background="pink">
    <TextBlock Text="This is the User module Control"
               VerticalAlignment="Top"
               />
    <TextBlock Text="{Binding Path=DataContext.MainWinVMString, RelativeSource={RelativeSource  AncestorType={x:Type Window}}}"
               VerticalAlignment="Bottom"
               />
</Grid>

完整的工作示例: https://1drv.ms/u/s!AmPvL3r385QhgqIZUul-ppiIHZ9uyA