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

相关推荐
wuli_滔滔1 天前
【探索实战】深入浅出:使用Kurator Fleet实现跨云集群的统一应用分发
架构·wpf·kurator·fleet
松☆1 天前
Flutter 与 OpenHarmony 深度集成:自定义 MethodChannel 插件开发全指南
flutter·wpf
Aevget1 天前
界面控件DevExpress WPF中文教程:Data Grid - 虚拟源限制
hadoop·wpf·界面控件·devexpress·ui开发
听风吟丶1 天前
Java 微服务日志实战:ELK+SkyWalking 构建全链路日志监控与智能告警体系某电商平台曾因日志问题陷入
wpf
她说彩礼65万1 天前
WPF 样式
大数据·hadoop·wpf
她说彩礼65万1 天前
WPF Behavior
wpf
她说彩礼65万1 天前
WPF Binding Source
大数据·hadoop·wpf
Aevget1 天前
界面控件DevExpress WPF v25.1新版亮点:富文本编辑器全新升级
开发语言·c#·wpf·devexpress·用户界面
张人玉1 天前
WPF中无框架、Prism 框架、CommunityToolkit.Mvvm 框架的区别
c#·wpf·prism
张人玉2 天前
Prism 框架笔记及实例
c#·wpf·prism