首页 > 解决方案 > 如何使用 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;
        }
    }
}

先感谢您。

标签: c#.netwpfxamlmvvm

解决方案


推荐阅读