WPF 使用UserControl / ContentControl显示子界面

想把一个东西很多的界面拆分一下,拆成几个小界面再拼接起来,脑袋里有UserControl / ContentControl这些概念,但是不知道具体怎么实现,记录一下两种方法:

法一:UserControl实现

主界面View:

XML 复制代码
<Page x:Class="Lithography.View.MainPage"
      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:telerik="http://schemas.telerik.com/2008/xaml/presentation"
      xmlns:lc="clr-namespace:FluentVision.Controls;assembly=FluentVision.Controls"
      xmlns:sonPage="clr-namespace:Lithography.View.SonPage"
      d:DesignHeight="600"
      d:DesignWidth="800"
      mc:Ignorable="d">
    
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <!-- 平台运动控制模块 -->
        <sonPage:PlatformMovementControlPage 
            Grid.Row="0" Grid.Column="0"
            DataContext="{Binding PlatformMovement}"
            Margin="5"/>

        <!-- 真空控制模块 -->
        <sonPage:VacuumControlPage 
            Grid.Row="0" Grid.Column="1"
            DataContext="{Binding VacuumControl}"
            Margin="5"/>

        <!-- IO状态显示模块 -->
        <sonPage:IoStatusPage 
            Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2"
            DataContext="{Binding IoStatus}"
            Margin="5"/>
    </Grid>
</Page>

主界面ViewModel

cs 复制代码
using ReactiveUI;

namespace Lithography.ViewModel
{
    public class MainViewModel : ReactiveObject
    {
        public PlatformMovementControlViewModel PlatformMovement { get; }
        public VacuumControlViewModel VacuumControl { get; }
        public IoStatusViewModel IoStatus { get; }

        public MainViewModel()
        {
            PlatformMovement = new PlatformMovementControlViewModel();
            VacuumControl = new VacuumControlViewModel();
            IoStatus = new IoStatusViewModel();
        }
    }
}

主界面声明这些子对象是为了给子界面提供数据源(DataContext绑定),也可以直接在子界面窗体构造函数中指定数据源:

当然还要集合具体使用的MVVM框架,寻求更好实现;

法二:ContentControl + DataTemplate

主界面View:

XML 复制代码
<Page x:Class="Lithography.View.MainPage"
      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:telerik="http://schemas.telerik.com/2008/xaml/presentation"
      xmlns:viewModels="clr-namespace:Lithography.ViewModel.SonPage"
      d:DesignHeight="600"
      d:DesignWidth="800"
      mc:Ignorable="d">
    
    <Page.Resources>
        <!-- 定义 ViewModel 到 View 的映射 -->
        <DataTemplate DataType="{x:Type viewModels:PlatformMovementControlViewModel}">
            <sonPage:PlatformMovementControlPage/>
        </DataTemplate>
        
        <DataTemplate DataType="{x:Type viewModels:VacuumControlViewModel}">
            <sonPage:VacuumControlPage/>
        </DataTemplate>
        
        <DataTemplate DataType="{x:Type viewModels:IoStatusViewModel}">
            <sonPage:IoStatusPage/>
        </DataTemplate>
    </Page.Resources>
    
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <!-- 使用 ContentControl 自动选择模板 -->
        <ContentControl 
            Grid.Row="0" Grid.Column="0"
            Content="{Binding PlatformMovement}"
            Margin="5"/>
            
        <ContentControl 
            Grid.Row="0" Grid.Column="1"
            Content="{Binding VacuumControl}"
            Margin="5"/>
            
        <ContentControl 
            Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2"
            Content="{Binding IoStatus}"
            Margin="5"/>
    </Grid>
</Page>

主界面ViewModel:

cs 复制代码
 public class MainViewModel : ReactiveObject
    {
        public PlatformMovementControlViewModel PlatformMovement { get; }
        public VacuumControlViewModel VacuumControl { get; }
        public IoStatusViewModel IoStatus { get; }

        public MainViewModel()
        {
            PlatformMovement = new PlatformMovementControlViewModel();
            VacuumControl = new VacuumControlViewModel();
            IoStatus = new IoStatusViewModel();
        }
    }

ContentControl严格上来说也是一个控件,是常见的Button、ScrollViewer的基类:

ContentControl 的 Content 属性的类型为 Object(同样Button的Content也是,只不过常用来显示文本,也可以显示图片和其他布局控件等等),这里在主界面把 ContentControl 的Content 绑定上后台子界面ViewModel,然后设置了ContentControl的ContentTemplate属性,ContentTemplate是DataTemplate类型,注意上方xaml 窗体资源中定义的DataTemplate就是变相指定了ContentControl的ContentTemplate属性,还可以下面这样写:

cs 复制代码
<Window x:Class="_11_4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <DataTemplate x:Key="datatemplate1">
            <StackPanel Orientation="Horizontal">
                <CheckBox/>
                <TextBlock Text=" Hello World"/>
            </StackPanel>
        </DataTemplate>
    </Window.Resources>
    <Grid>
        <Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="153,26,0,0" Name="button1" VerticalAlignment="Top" Width="130" 
                ContentTemplate="{StaticResource datatemplate1}"/>
        <Label Content="Label" Height="28" HorizontalAlignment="Left" Margin="153,68,0,0" Name="label1" VerticalAlignment="Top" Width="130" 
               ContentTemplate="{StaticResource datatemplate1}"/>
        <ScrollViewer Height="23" HorizontalAlignment="Left" Margin="153,127,0,0" Name="scrollViewer1" VerticalAlignment="Top" Width="120" 
                ContentTemplate="{StaticResource datatemplate1}"/>
        
    </Grid>
</Window>

或者:

XML 复制代码
<Button>
    <Button.ContentTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <Image Source="/Icons/settings.png" Width="16" Height="16" Margin="0,0,5,0"/>
                <TextBlock Text="设置" VerticalAlignment="Center"/>
            </StackPanel>
        </DataTemplate>
    </Button.ContentTemplate>
</Button>

...很多种写法,想了解的话可以问一下AI,我就不愿意列举了。

部分代码引用自:https://blog.csdn.net/lzhui1987/article/details/51878861?fromshare=blogdetail&sharetype=blogdetail&sharerId=51878861&sharerefer=PC&sharesource=qq_59062726&sharefrom=from_link

相关推荐
Chris _data16 天前
WPF 学习第三天 — Modbus RTU 串口通信
hadoop·学习·wpf
布吉岛的石头17 天前
Java 程序员第 43 阶段05:微服务整合大模型,跨服务调用架构设计实战,Seata分布式事务实战
wpf
步步为营DotNet17 天前
基于.NET Aspire 实现云原生应用的高效监控与可观测性
云原生·.net·wpf
芒鸽17 天前
HarmonyOS 分布式开发实战:设备协同、数据共享与跨设备迁移
分布式·wpf·harmonyos
Volunteer Technology17 天前
Flink状态管理与容错(二)
大数据·flink·wpf
happyprince18 天前
07_verl-Trainer模块详解
人工智能·架构·wpf·强化学习
bugcome_com18 天前
WPF + Prism 技术指南与实战项目(二、模板搭建)
wpf
小满Autumn19 天前
log4net 日志框架 — 从配置到实战速查手册
笔记·c#·.net·wpf·上位机·log4net
政沅同学19 天前
基于 C# WPF + HALCON 的工业视觉算法工具框架(开源)
开发语言·c#·wpf
happyprince19 天前
03_verl-设计理念与核心原理
wpf