前言 WPF 窗口 页 用户控件的区别
在 WPF 中,窗口(Window)、页面(Page)和用户控件(User Control)是三种常见的可视化元素,它们在应用程序中扮演不同的角色。
窗口(Window) :窗口是一个独立的顶级容器,通常表示应用程序的主界面或者一个模式对话框。
窗口可以包含其他的 WPF 控件,如按钮、文本框等,并且可以具有标题栏、最大化、最小化和关闭按钮等标准窗口功能。
页面(Page) :页面是一种特殊的控件,用于创建具有导航功能的应用程序。
页面通常用于创建多个相关内容的视图,并且可以通过导航服务在这些视图之间进行切换。
在 WPF 应用程序中,通常使用 Frame 控件来承载页面,并且可以通过 Frame 的导航功能在不同的页面之间导航。
用户控件(UserControl) :用户控件是一种自定义的可重用控件,它可以包含其他的 WPF 控件,并且可以定义自己的布局和行为。
用户控件通常用于封装一些常用的 UI 元素或者功能,以便在应用程序中多次重用。
与页面不同,用户控件通常不具有导航功能,而是被设计为嵌入到其他容器中使用。
总的来说,窗口用于表示应用程序的顶级界面,页面用于创建具有导航功能的视图,而用户控件用于封装和重用 UI 元素或功能。
Page 以下是一个简单的示例,演示如何在 WPF 中创建和使用页面:
MainWindow.xaml 包含一个 Frame 控件,用于承载页面。
MainWindow.xaml :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <Window x:Class ="WpfApp.MainWindow" xmlns ="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x ="http://schemas.microsoft.com/winfx/2006/xaml" Title ="Main Window" Height ="450" Width ="800" > <Grid > <Grid.ColumnDefinitions > <ColumnDefinition /> <ColumnDefinition /> </Grid.ColumnDefinitions > <Button Content ="Go to Page 1" Click ="GoToPage1_Click" HorizontalAlignment ="Center" VerticalAlignment ="Center" Margin ="10" /> <Button Content ="Go to Page 2" Click ="GoToPage2_Click" Grid.Column ="1" HorizontalAlignment ="Center" VerticalAlignment ="Center" Margin ="10" /> <Frame x:Name ="MainFrame" Grid.ColumnSpan ="2" NavigationUIVisibility ="Hidden" /> </Grid > </Window >
MainWindow.xaml.cs :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 using System.Windows;namespace WpfApp { public partial class MainWindow : Window { public MainWindow () { InitializeComponent(); } private void GoToPage1_Click (object sender, RoutedEventArgs e ) { MainFrame.NavigationService.Navigate(new Page1()); } private void GoToPage2_Click (object sender, RoutedEventArgs e ) { MainFrame.NavigationService.Navigate(new Page2()); } } }
在这个示例中,MainWindow 中有两个按钮,分别用于导航到 Page1 和 Page2。
点击不同的按钮会切换到对应的页面。
Page1.xaml :
1 2 3 4 5 6 7 8 9 <Page x:Class ="WpfApp.Page1" xmlns ="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x ="http://schemas.microsoft.com/winfx/2006/xaml" Title ="Page 1" > <Grid > <TextBlock Text ="This is Page 1" HorizontalAlignment ="Center" VerticalAlignment ="Center" FontSize ="24" /> <Button Content ="Go to Page 2" Click ="GoToPage2_Click" HorizontalAlignment ="Center" VerticalAlignment ="Bottom" Margin ="0,0,0,50" /> </Grid > </Page >
Page1.xaml.cs :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 using System.Windows;using System.Windows.Controls;namespace WpfApp { public partial class Page1 : Page { public Page1 () { InitializeComponent(); } private void GoToPage2_Click (object sender, RoutedEventArgs e ) { NavigationService.Navigate(new Page2()); } } }
Page2.xaml :
1 2 3 4 5 6 7 8 <Page x:Class ="WpfApp.Page2" xmlns ="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x ="http://schemas.microsoft.com/winfx/2006/xaml" Title ="Page 2" > <Grid > <TextBlock Text ="This is Page 2" HorizontalAlignment ="Center" VerticalAlignment ="Center" FontSize ="24" /> </Grid > </Page >
Page2.xaml.cs :
1 2 3 4 5 6 7 8 9 10 11 12 using System.Windows.Controls;namespace WpfApp { public partial class Page2 : Page { public Page2 () { InitializeComponent(); } } }
当点击 Page1 中的按钮时,会导航到 Page2。
UserControl 组件化我们都用UserControl实现。
以下是一个简单的示例,演示如何创建和使用用户控件(UserControl):
MyUserControl.xaml :
1 2 3 4 5 6 7 8 9 10 11 <UserControl x:Class ="WpfApp.MyUserControl" 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" mc:Ignorable ="d" d:DesignHeight ="450" d:DesignWidth ="800" > <Grid > <TextBlock Text ="This is my user control!" HorizontalAlignment ="Center" VerticalAlignment ="Center" FontSize ="24" /> </Grid > </UserControl >
MyUserControl.xaml.cs :
1 2 3 4 5 6 7 8 9 10 11 12 using System.Windows.Controls;namespace WpfApp { public partial class MyUserControl : UserControl { public MyUserControl () { InitializeComponent(); } } }
MainWindow.xaml :
1 2 3 4 5 6 7 8 9 <Window x:Class ="WpfApp.MainWindow" xmlns ="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x ="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local ="clr-namespace:WpfApp" Title ="Main Window" Height ="450" Width ="800" > <Grid > <local:MyUserControl /> </Grid > </Window >
在这个示例中,MyUserControl.xaml 包含一个简单的 TextBlock,用于显示文本。
然后在 MainWindow.xaml 中将这个用户控件嵌入到了 Grid 中。
组件传值 自定义组件 假如我的自定义UserControl的类是UcBlackbord
添加
1 2 3 4 5 6 7 8 9 10 11 12 13 public static readonly DependencyProperty ShowToolbarProperty = DependencyProperty.Register( nameof (ShowToolbar), typeof (bool ), typeof (UcBlackbord), new PropertyMetadata(false ) ); public bool ShowToolbar{ get => (bool )GetValue(ShowToolbarProperty); set => SetValue(ShowToolbarProperty, value ); }
UcBlackbord的xaml中绑定值的方式
1 Visibility="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:UcBlackbord}}, Path=ShowToolbar, Converter={StaticResource BooleanToVisibilityConverter}}"
引用 在引用组件的地方传值
1 2 3 4 5 6 7 8 9 10 11 <DataTemplate x:Key ="BlackbordTpl" DataType ="page:SubmitUserItem" > <Border Name ="OuterBorder" BorderBrush ="{Binding Path=Selected, Converter={StaticResource ZGenericTypeConverter}, ConverterParameter='true:#339DFF|other:#00ffffff'}" BorderThickness ="2" Focusable ="True" PreviewMouseDown ="UIElement_OnMouseDown" Tag ="{Binding}" > <uc:UcBlackbord ShowToolbar ="{Binding DataContext.Selected, ElementName=OuterBorder}" /> </Border > </DataTemplate >
注意下面的写法是有问题的,他会在组件内查找属性
1 <uc:UcBlackbord ShowToolbar ="{Binding Selected}" />
组件绑定事件 要在 WPF 自定义 UserControl 中绑定事件并传值,可以通过以下步骤实现:
创建自定义组件 首先,创建一个自定义的 UserControl,并在其中定义事件以及需要传递的值。
1 2 3 4 5 6 7 8 <UserControl x:Class ="YourNamespace.MyUserControl" xmlns ="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x ="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local ="clr-namespace:YourNamespace" x:Name ="root" > <Button Content ="Click Me" Click ="Button_Click" /> </UserControl >
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 using System;using System.Windows;using System.Windows.Controls;namespace YourNamespace { public partial class MyUserControl : UserControl { public event EventHandler<string > ValueSelected; public MyUserControl () { InitializeComponent(); } private void Button_Click (object sender, RoutedEventArgs e ) { ValueSelected?.Invoke(this , "Hello from UserControl!" ); } } }
使用组件并订阅事件 在主窗口中使用自定义 UserControl 并订阅事件
在主窗口中使用自定义的 UserControl,并订阅其事件,接收传递的值:
1 2 3 4 5 6 7 8 9 10 11 <Window x:Class ="YourNamespace.MainWindow" xmlns ="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x ="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local ="clr-namespace:YourNamespace" Title ="MainWindow" Height ="450" Width ="800" > <Grid > <local:MyUserControl ValueSelected ="MyUserControl_ValueSelected" /> </Grid > </Window >
页面代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 using System.Windows;namespace YourNamespace { public partial class MainWindow : Window { public MainWindow () { InitializeComponent(); } private void MyUserControl_ValueSelected (object sender, string e ) { string value = e; MessageBox.Show(value ); } } }
在这个示例中,当用户点击 UserControl 中的按钮时,触发了 ValueSelected 事件,并传递了一个字符串值。
在主窗口中订阅了这个事件,可以收到传递的值并进行相应处理。
这样就实现了在自定义 UserControl 中绑定事件并传值的功能。