我试图了解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代码后面)?
答案 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>