Как получить доступ к модели представления MainWindow из Page? - PullRequest
0 голосов
/ 23 декабря 2018

Я пытаюсь понять систему привязки в WPF.В моем примере мне нужно получить доступ к модели представления MainWindow из Page в XAML.

У меня есть одно решение для реализации этого.Но я хочу узнать больше разных способов

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 и в codebehind)?Как получить доступ к другому текстовому тексту в XAML (как в моем коде StartPage)?

1 Ответ

0 голосов
/ 23 декабря 2018

Коротким ответом на привязку дочернего элемента управления к свойству в текстовом тексте родительского окна является родственный источник, например:

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

Viewmodel для этого:

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));
        }
    }
}

Команда Relay из пакета 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

...