c# - 如何使用 WPF MVVM 中的命令将 DataContext 传递给 UserControl?
问题描述
我正在练习使用带有 YouTube 视频的 WPF MVVM。我在主窗口和用户控件中制作了菜单按钮,当我单击菜单时,用户控件显示在主窗口中。MainViewModel 有 UserControl 的每个 ViewModel,显示的 UserControl 是通过改变 MainViewModel 中的 CurrentView 来改变的。
我想在初始化之前在 UserControl 中设置 DataContext,但我不知道如何。我试图更改 MainViewModel 中的 ViewModel 成员值,但 UserControl 中的实际 DataContext 成员变量只是 null。
我想问的是如何在 UserControl 初始化时设置 DataContext 。或者有什么方法可以从 MainWindow 访问 DataContext?
我的代码如下:
应用程序.xaml
<Application x:Class="Practice.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Practice"
xmlns:viewModel="clr-namespace:Practice.MVVM.ViewModel"
xmlns:view="clr-namespace:Practice.MVVM.View"
Startup="Application_Startup">
<Application.Resources>
<ResourceDictionary>
<DataTemplate DataType="{x:Type viewModel:HomeViewModel}">
<view:HomeView/>
</DataTemplate>
<DataTemplate DataType="{x:Type viewModel:UserViewModel}">
<view:UserView/>
</DataTemplate>
</ResourceDictionary>
</Application.Resources>
</Application>
主窗口.xaml
<Window x:Class="Practice.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Practice"
xmlns:viewModel="clr-namespace:Practice.MVVM.ViewModel"
xmlns:view="clr-namespace:Practice.MVVM.View"
mc:Ignorable="d"
Title="Practice" MinHeight="800" MinWidth="1200"
WindowStyle="None"
ResizeMode="NoResize"
Background="Transparent"
AllowsTransparency="True"
Loaded="Window_Loaded">
<Window.DataContext>
<viewModel:MainViewModel/>
</Window.DataContext>
<Border Background="#002241"
CornerRadius="10">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="100"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0"
Text="Logo"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="20"
Foreground="White"/>
<Grid Grid.Row="1" Grid.Column="0">
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="75"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0">
<RadioButton Content="Home"
Height="50"
Foreground="White"
FontSize="16"
IsChecked="True"
Command="{Binding HomeViewCommand}"/>
<RadioButton Content="Users"
Height="50"
Foreground="White"
FontSize="16"
Command="{Binding UserViewCommand}"/>
</StackPanel>
</Grid>
<ContentControl Grid.Row="1" Grid.Column="1"
x:Name="CC_View"
Margin="10"
Content="{Binding CurrentView}"/>
</Grid>
</Border>
</Window>
主页视图.xaml
<UserControl x:Class="Practice.MVVM.View.HomeView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Practice.MVVM.View"
xmlns:viewModel="clr-namespace:Practice.MVVM.ViewModel"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.DataContext>
<viewModel:HomeViewModel/>
</UserControl.DataContext>
<Grid>
</Grid>
</UserControl>
ObservableObject.cs
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace Practice.Core
{
public class ObservableObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string name = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
}
中继命令.cs
using System;
using System.Windows.Input;
namespace Practice.Core
{
public class RelayCommand:ICommand
{
private Action<object> _execute;
private Func<object, bool> _canExecute;
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public RelayCommand(Action<object> execute, Func<object, bool> canExecute = null)
{
_execute = execute;
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return _canExecute == null || _canExecute(parameter);
}
public void Execute(object parameter)
{
_execute(parameter);
}
}
}
主视图模型.cs
namespace Practice.MVVM.ViewModel
{
public class MainViewModel : ObservableObject
{
public RelayCommand HomeViewCommand { get; set; }
public RelayCommand UserViewCommand { get; set; }
public HomeViewModel HomeVM { get; set; }
public UserViewModel UserVM { get; set; }
private object _currentView;
private object parameter1;
private object parameter2;
private object parameter3;
public object CurrentView
{
get { return _currentView; }
set
{
_currentView = value;
OnPropertyChanged();
}
}
public MainViewModel()
{
parameter1 = new object();
parameter2 = new object();
parameter3 = new object();
HomeVM = new HomeViewModel();
HomeVM.Initialize(parameter1, parameter2, parameter3);
UserVM = new UserViewModel();
CurrentView = HomeVM;
HomeViewCommand = new RelayCommand(o =>
{
CurrentView = HomeVM;
});
UserViewCommand = new RelayCommand(o =>
{
CurrentView = UserVM;
});
}
}
}
HomeViewModel.cs
namespace Practice.MVVM.ViewModel
{
public class HomeViewModel : ObservableObject
{
private object _parameter1;
private object _parameter2;
private object _parameter3;
public HomeViewModel()
{
}
public void Initialize(object parameter1, object parameter2, object parameter3)
{
_parameter1= parameter1;
_parameter2= parameter2;
_parameter3= parameter3;
}
}
}
先感谢您。
解决方案
推荐阅读
- javascript - 从选择元素中选择选项时,控制台日志加倍
- javascript - 使用 JavaScript 获取 textarea 值并将其插入到地图上
- ios - 如何在烛台图表的蜡烛顶部和底部绘制自定义视图
- sql - 访问数据库。VBA 查询
- objective-c - 如何用同一个对象(NSString)填充整个 NSMutableArray
- spring-boot - 如何在 feign client spriong Boot 中设置值
- python - 无法将超链接上传到列类型为超链接或图片的 SharePoint Online 列表
- nginx - 如何让 Kubernetes 服务负载均衡基于客户端 IP 而不是 NGINX 反向代理 IP
- flutter - MissingPluginException(在通道 com.tekartik.sqflite 上找不到方法 getDatabasesPath 的实现)
- c++ - 使编译器在类型擦除中使用 lambda 优化函数调用间接