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

WinUI 3中如何根据用户操作动态切换PersonPage的ContentControl视图

WinUI 3 实现根据用户操作切换ContentControl视图模板

问题描述

在WinUI 3的MainPage中,通过ListView展示人员列表,希望实现:

  • 点击ListView项时显示人员详情模板
  • 点击“Edit”按钮时显示编辑模板
  • 点击“New”按钮时显示新建人员模板

但当前代码运行后,ContentControl显示文本“App1.Core.Models.Person”,无法正确切换模板。

问题原因分析

  1. ContentControl绑定对象错误:当前Content绑定的是SelectedPerson,但模板选择器VisitTemplateSelector中判断的是MainViewModel类型,导致选择器逻辑无法匹配,最终调用默认逻辑显示对象的ToString()结果(即类型名称)。
  2. 模板选择器逻辑错误:
    • New模式的判断条件SelectedPerson is null && SelectedView == New永远无法满足,因为NewVisit方法中会创建新的Person对象赋值给SelectedPerson。
    • 条件顺序不合理,导致部分状态无法触发正确模板。
  3. 视图模板的x:DataType设置错误:详情模板的x:DataType设为MainViewModel,且文字颜色与背景色冲突导致内容不可见。

解决方案

1. 修正VisitTemplateSelector逻辑

调整选择器逻辑,正确基于MainViewModel的状态选择模板:

public class VisitTemplateSelector : DataTemplateSelector
{
    public DataTemplate? VisitEditTemplate { get; set; }
    public DataTemplate? VisitEmptyTemplate { get; set; }
    public DataTemplate? VisitNewTemplate { get; set; }
    public DataTemplate? VisitViewTemplate { get; set; }

    protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
    {
        if (item is MainViewModel viewModel)
        {
            // 优先处理新建模式
            if (viewModel.SelectedView == MainViewModel.ViewMode.New)
            {
                return VisitNewTemplate;
            }
            // 处理编辑模式
            if (viewModel.SelectedPerson != null && viewModel.SelectedView == MainViewModel.ViewMode.Edit)
            {
                return VisitEditTemplate;
            }
            // 处理查看模式
            if (viewModel.SelectedPerson != null && viewModel.SelectedView == MainViewModel.ViewMode.View)
            {
                return VisitViewTemplate;
            }
            // 默认空状态
            return VisitEmptyTemplate;
        }

        return base.SelectTemplateCore(item, container);
    }
}

2. 修正ContentControl绑定

将ContentControl的Content绑定到整个ViewModel,确保模板选择器能获取完整的状态信息:

<ContentControl x:Name="ContentView"
                ContentTemplateSelector="{StaticResource visitTemplateSelector}"
                Content="{x:Bind ViewModel, Mode=OneWay}" />

3. 修正视图模板

调整模板的x:DataType和绑定逻辑,优化显示效果:

<DataTemplate x:Key="visitEmptyTemplate">
    <StackPanel Orientation="Vertical" Background="Violet" Padding="20">
        <TextBlock Text="请选择人员或新建记录" Foreground="White" Style="{StaticResource SubtitleTextBlockStyle}"/>
    </StackPanel>
</DataTemplate>

<DataTemplate x:Key="visitEditTemplate" x:DataType="vm:MainViewModel">
    <StackPanel Background="LightBlue" Padding="10">
        <TextBlock Text="编辑人员信息" Style="{StaticResource SubtitleTextBlockStyle}" Margin="0 0 0 10"/>
        <TextBox Header="姓名" Text="{x:Bind SelectedPerson.Name, Mode=TwoWay}" Margin="0 0 0 5"/>
        <TextBox Header="电话" Text="{x:Bind SelectedPerson.Phone, Mode=TwoWay}"/>
    </StackPanel>
</DataTemplate>

<DataTemplate x:Key="visitNewTemplate" x:DataType="vm:MainViewModel">
    <StackPanel Background="LightGreen" Padding="10">
        <TextBlock Text="新建人员信息" Style="{StaticResource SubtitleTextBlockStyle}" Margin="0 0 0 10"/>
        <TextBox Header="姓名" Text="{x:Bind SelectedPerson.Name, Mode=TwoWay}" Margin="0 0 0 5"/>
        <TextBox Header="电话" Text="{x:Bind SelectedPerson.Phone, Mode=TwoWay}"/>
    </StackPanel>
</DataTemplate>

<DataTemplate x:Key="visitViewTemplate" x:DataType="vm:MainViewModel">
    <StackPanel Orientation="Vertical" Background="Indigo" Padding="10">
        <TextBlock Text="人员详情" Style="{StaticResource SubtitleTextBlockStyle}" Foreground="White" Margin="0 0 0 10"/>
        <TextBlock Text="姓名:{x:Bind SelectedPerson.Name, Mode=OneWay}" Foreground="White" Margin="0 0 0 5"/>
        <TextBlock Text="电话:{x:Bind SelectedPerson.Phone, Mode=OneWay}" Foreground="White"/>
    </StackPanel>
</DataTemplate>

4. 确保Person类支持属性变更通知

如果Person类未实现INotifyPropertyChanged,需修改为:

using CommunityToolkit.Mvvm.ComponentModel;

namespace App1.Core.Models;

public partial class Person : ObservableObject
{
    [ObservableProperty]
    private string? _name;

    [ObservableProperty]
    private string? _phone;
}

验证效果

修改完成后:

  • 程序启动时显示空状态模板
  • 点击ListView项,自动切换到详情模板展示人员信息
  • 选中人员后点击“Edit”按钮,切换到编辑模板可修改信息
  • 点击“New”按钮,切换到新建模板创建新人员记录

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 06:18:09