如何从 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>
我想了解 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>