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

时间:2018-12-23 12:25:28

标签: c# wpf xaml mvvm viewmodel

我试图了解WPF中的绑定系统。在我的示例中,我需要从XAML中的Page访问MainWindow视图模型。

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

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代码后面)?

1 个答案:

答案 0 :(得分:0)

将子控件绑定到父窗口的数据上下文中的属性的简短答案是relativesource,例如:

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

以下是一个示例,可以为您提供我所建议的风味。

MainWindow标记有点麻烦。 我会将数据模板放在由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));
        }
    }
}

中继命令来自nuget包mvvmlightlibs。

UserUC:

<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