You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何根据ViewModel切换ContentTemplate及指定视图显示?

WPF根据ViewModel自动切换视图的正确实现方式

问题分析

你当前的写法存在错误:Window.ContentTemplate只能指定单个模板,无法直接放置多个DataTemplate。正确的做法是将对应ViewModel的视图模板放到窗口资源中,通过ContentControl自动匹配渲染。

完整实现代码

1. 定义ViewModel基类(实现属性变更通知)

using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace Pandora.ViewModels
{
    public class ViewModelBase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler? PropertyChanged;

        protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

2. 编写具体业务ViewModel

namespace Pandora.ViewModels
{
    public class IndexViewModel : ViewModelBase
    {
        // 可添加Index视图所需的属性与业务逻辑
    }

    public class DashboardViewModel : ViewModelBase
    {
        // 可添加Dashboard视图所需的属性与业务逻辑
    }
}

3. 编写主ViewModel(管理当前视图切换)

namespace Pandora.ViewModels
{
    public class MainViewModel : ViewModelBase
    {
        private ViewModelBase _currentViewModel;

        public ViewModelBase CurrentViewModel
        {
            get => _currentViewModel;
            set
            {
                _currentViewModel = value;
                OnPropertyChanged();
            }
        }

        // 切换到Index视图
        public void SwitchToIndex()
        {
            CurrentViewModel = new IndexViewModel();
        }

        // 切换到Dashboard视图
        public void SwitchToDashboard()
        {
            CurrentViewModel = new DashboardViewModel();
        }
    }
}

4. 修改MainWindow的XAML

<Window x:Class="Pandora.Views.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:vm="clr-namespace:Pandora.ViewModels"
        Title="Pandora" Height="350" Width="525">
    <Window.Resources>
        <!-- IndexViewModel对应的视图模板 -->
        <DataTemplate DataType="{x:Type vm:IndexViewModel}">
            <Grid>
                <TextBlock Text="Index Content" FontSize="20" HorizontalAlignment="Center" VerticalAlignment="Center"/>
                <Button Content="切换到Dashboard" HorizontalAlignment="Bottom" VerticalAlignment="Bottom" Margin="20"
                        Command="{Binding DataContext.SwitchToDashboard, RelativeSource={RelativeSource AncestorType=Window}}"/>
            </Grid>
        </DataTemplate>

        <!-- DashboardViewModel对应的视图模板 -->
        <DataTemplate DataType="{x:Type vm:DashboardViewModel}">
            <Grid>
                <TextBlock Text="Dashboard Content" FontSize="20" HorizontalAlignment="Center" VerticalAlignment="Center"/>
                <Button Content="切换到Index" HorizontalAlignment="Bottom" VerticalAlignment="Bottom" Margin="20"
                        Command="{Binding DataContext.SwitchToIndex, RelativeSource={RelativeSource AncestorType=Window}}"/>
            </Grid>
        </DataTemplate>
    </Window.Resources>

    <!-- 用ContentControl承载当前视图 -->
    <Grid>
        <ContentControl Content="{Binding CurrentViewModel}"/>
    </Grid>
</Window>

5. 修改MainWindow后台代码

using Pandora.ViewModels;

namespace Pandora.Views;

public partial class MainWindow
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = new MainViewModel()
        {
            // 默认显示Index视图
            CurrentViewModel = new IndexViewModel()
        };
    }
}

核心原理

  • WPF会自动根据DataTemplate的DataType属性,匹配ContentControl中Content对应的ViewModel类型,自动渲染对应的视图。
  • 当MainViewModel的CurrentViewModel属性变更时,由于实现了INotifyPropertyChanged接口,ContentControl会收到变更通知,自动切换到新ViewModel对应的视图。

内容的提问来源于stack exchange,提问作者blazer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 17:40:30