视频相关链接:https://www.bilibili.com/video/BV1iY411w7zD
Windows Presentation Foundation (简称 WPF)
WPF 的核心是一个与分辨率无关且基于矢量的呈现引擎,旨在充分利用现代图形硬件。 WPF 通过一套完善的应用程序开发功能对该核心进行了扩展,这些功能包括可扩展应用程序标记语言 (XAML)、控件、数据绑定、布局、二维和三维图形、动画、样式、模板、文档、媒体、文本和版式。 WPF 属于 .NET,因此可以生成整合 .NET API 其他元素的应用程序。
Windows用户界面框架,统一的编程模型、语言和框架,做到了界面设计与后端开发分离。
1.呈现效果不受分辨率的影响
2.基于DirectX 3d技术,可以做出炫酷的界面
3.提供UI框架,集成了矢量图形、流动文字支持、3d视觉效果和控件模型框架、
4. UI与业务逻辑彻底分离,UI-XAML描述(底层wpf引擎是把元素解释成对应的对象)
5. xp server2003 到 window7及以后的操作系统版本 都可以支持
6.基于数据驱动,数据是核心
基础:首先我们需要先入门C# / VB
开发工具: Visual Studio 2019
(下载链接: https://pan.baidu.com/s/1uMH8C2rg5T8pNXrObXddXw 提取码: hatd )
框架环境: .net core 3.1 或者.net framework4.0+
System.Windows.Controls (程序集:PresentationFramework.dll) | ||
---|---|---|
文档地址:https://docs.microsoft.com/zh-cn/dotnet/api/system.windows.controls?view=windowsdesktop-6.0 | ||
Label (表示控件的文本标签,并提供访问密钥支持。) | TextBox(显示或编辑无格式文本) | TextBlock(一个轻型控件,用于显示少量流内容) |
Border (边框控件 ,作用 在另一个元素四周绘制边框和/或背景) |
Button(按钮控件) | Calendar (日历控件) |
CheckBox(选择框) | ComboBox (下拉框) | Image (图片控件) |
Menu(菜单) | ContextMenu(内容菜单) | RadioButton(表示可由用户选择但不能清除的按钮,代码能清除) |
DataGrid(数据网格–Table) | ListBox(包含可选项列表) | ListView(表示用于显示数据项列表的控件) |
DockPanel(定义一个区域,从中可以按相对位置水平或垂直排列各个子元素。)—码头;港区 | Grid(定义由列和行组成的灵活的网格区域。) | GroupBox(组控件— 表示一个控件,该控件用于创建具有用户界面 (UI) 内容边框和标题的容器。) |
PrintDialog(调用标准的 Microsoft Windows 打印对话框) | ProgressBar(指示操作进度) | Canvas (画布控件) |
RichTextBox(表示对 FlowDocument 对象进行操作的丰富编辑控件) | ToolBar(一组命令或控件提供容器) | Expander(折叠控件) 表示一种控件,该控件显示具有可折叠内容显示窗口的标题。 |
TabControl(表示包含多个项的控件,这些项共享屏幕上的同一空间) | Frame(一种支持导航的内容控件) | Rectangle(矩形区域) |
StackPanel(将子元素排列成水平或垂直的一行。) | WrapPanel (按从左到右的顺序位置定位子元素,在包含框的边缘处将内容切换到下一行。) |
XAML 是一种声明性标记语言。 应用于 .NET Core 编程模型时,XAML 简化了为 .NET Core 应用创建 UI 的过程。 XAML 文件是通常具有 .xaml 扩展名的 XML 文件。 可通过任何 XML 编码对文件进行编码,但通常以 UTF-8 编码。
<StackPanel>
<Button Content="Click Me"/>
</StackPanel>
对象元素语法 是 XAML 标记语法,它通过声明 XML 元素来实例化 CLR 类或结构。 此语法类似于其他标记语言(如 HTML)的元素语法。
一个 XAML 文件只能有一个根元素,这样才能同时作为格式正确的 XML 文件和有效的 XAML 文件。 对于典型 WPF 方案,可使用在 WPF 应用模型中具有突出意义的根元素(例如,页面的 Window 或 Page)。
在根标签下面有且只能有一个二级标签。在二级标签里面我们可以写多个三级 四级标签。
<Window>
<【布局标签】>
【其他标签....】
【布局标签】>
Window>
<Page>
<Window.Resources>
....
Window.Resources>
<【布局标签】>
【其他标签....】
【布局标签】>
Page>
在许多 XAML 文件的根标记中的命名空间声明内,通常可看到两个 XML 命名空间声明。 第一个声明默认映射整个 WPF 客户端/框架 XAML 命名空间:
xmlns=“http://schemas.microsoft.com/winfx/2006/xaml/presentation”
第二个声明映射单独的 XAML 命名空间,(通常)将其映射到 x: 前缀。
xmlns:x=“http://schemas.microsoft.com/winfx/2006/xaml”
这些声明之间的关系是 x: 前缀映射支持作为 xaml 语言定义一部分的内部函数,而 WPF 是一种将 xaml 用作语言的实现,并为 xaml 定义了其对象的词汇。
<Window x:Class="MyWpfApp.MainWindow"
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:local="clr-namespace:MyWpfApp"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800"
>
//d 表达式
//mc 标记兼容性
<【布局标签】 >
【布局标签】>
Window>
(CLR指的是公共语言运行库)
<Window x:Class="Ken.Wpf.移动方块.WindowMoveBox"
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:local="clr-namespace:Ken.Wpf.移动方块"
mc:Ignorable="d"
Title="WindowMoveBox" Height="450" Width="800" KeyDown="Grid_KeyDown">
<Grid ShowGridLines="True" Background="Teal" Name="gridContent">
<Grid.ColumnDefinitions>
<ColumnDefinition>ColumnDefinition>
<ColumnDefinition>ColumnDefinition>
<ColumnDefinition>ColumnDefinition>
Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition>RowDefinition>
<RowDefinition>RowDefinition>
<RowDefinition>RowDefinition>
Grid.RowDefinitions>
<Border Name="b1" Background="Transparent" Grid.Row="0" Grid.Column="0">Border>
<Border Name="b2" Background="White" Grid.Row="0" Grid.Column="1">Border>
<Border Name="b3" Background="Transparent" Grid.Row="0" Grid.Column="2">Border>
<Border Name="b4" Background="Transparent" Grid.Row="1" Grid.Column="0">Border>
<Border Name="b5" Background="Transparent" Grid.Row="1" Grid.Column="1">Border>
<Border Name="b6" Background="Transparent" Grid.Row="1" Grid.Column="2">Border>
<Border Name="b7" Background="Transparent" Grid.Row="2" Grid.Column="0">Border>
<Border Name="b8" Background="Transparent" Grid.Row="2" Grid.Column="1">Border>
<Border Name="b9" Background="Transparent" Grid.Row="2" Grid.Column="2">Border>
Grid>
Window>
private void Grid_KeyDown(object sender, KeyEventArgs e)
{
//首先判断按键的方位 比如上下左右
//向上移动 移到格子每次减3 向下移动 移到格子每次加3
//向左移动 每次减1 向右移动 每次加1
//获取白色的border元素
UIElementCollection children = gridContent.Children;
Border curBorder =null;
for (int i = 0; i < children.Count; i++)
{
if (children[i] is Border )
{
if(((children[i] as Border).Background as SolidColorBrush).Color.Equals(Colors.White))
{
curBorder = children[i] as Border;
}
(children[i] as Border).Background = new SolidColorBrush(Colors.Transparent);
}
}
string name = curBorder.Name;
int index = Convert.ToInt32(name.Replace("b", ""));
if (e.Key.Equals(Key.Up))//上
{
index = index - 3 >= 1 ? index - 3 : index;
}
else if (e.Key.Equals(Key.Down))//下
{
index = index + 3 <= 9 ? index + 3 : index;
}
else if(e.Key.Equals(Key.Left))//左
{
index = index - 1 >= 1 ? index - 1 : index;
}
else if (e.Key.Equals(Key.Right))//右
{
index = index +1 <=9 ? index +1 : index;
}
object control = gridContent.FindName("b" + index);
if (control != null)
{
(control as Border).Background = new SolidColorBrush(Colors.White);
}
}
对象:System.Windows.FrameworkElement | ||
---|---|---|
属性 | ||
属性名 | 对象类型 | 作用 |
Width | double | 获取或设置元素的宽度。【(元素的高度(以 与设备无关的单位(每个单位 1/96 英寸) 为单位)。 )】 |
Height | double | 获取或设置元素的高度。【元素的高度(以 与设备无关的单位(每个单位 1/96 英寸) 为单位)。 】 |
ActualWidth | double | 获取此元素的呈现的宽度。 |
ActualHeight | double | 获取此元素的呈现的高度。 |
Name | string | 获取或设置元素的标识名称。 该名称提供引用,以便代码隐藏(如事件处理程序代码)可以引用标记元素(在 XAML 处理器的处理过程中构造该元素之后)。 |
Style | Style | 获取或设置此元素呈现时所使用的样式。 |
Margin | Thickness | 获取或设置元素的外边距。 |
HorizontalAlignment | HorizontalAlignment | 获取或设置在父元素(如 Panel 或项控件)中组合此元素时所应用的水平对齐特征。【水平对齐设置,它是一个枚举值。】 |
VerticalAlignment | VerticalAlignment | 获取或设置在父元素(如面板或项控件)中组合此元素时所应用的垂直对齐特征。 |
FocusVisualStyle | Style | 获取或设置一个属性,该属性允许自定义此元素在捕获到键盘焦点时要应用于此元素的外观、效果或其他样式特征。 |
FlowDirection | FlowDirection | 获取或设置方向,文本和其他 用户界面 (UI) 元素在任何控制其布局的父元素中都按此方向流动。 |
DataContext | object | 获取或设置元素参与数据绑定时的数据上下文。 |
Resources | ResourceDictionary | 获取或设置本地定义的资源字典。 |
方法 | ||
方法名 | 参数 | 作用 |
BringIntoView | 尝试将此元素放入视图,它包含在任何可滚动区域内。 | |
BringIntoView(Rect targetRectangle) | 指定也放入视图的元素的大小。(targetRectangle) | 尝试将放入视图,它包含在任何可滚动区域内的此元素提供的区域大小。 |
FindName(string name) | 所请求元素的名称(name) | 查找具有提供的标识符名的元素。 |
FindResource(object resourceKey) | 所请求的资源键标识符(resourceKey) | 搜索具有指定键的资源并在引发异常,如果找不到所请求的资源。 |
事件 | ||
事件名称 | 作用 | |
Loaded | 当对元素进行布局、呈现,且可将其用于交互时发生。 | |
KeyDown | 当焦点在该元素上时按下某个键后发生。 | |
GotFocus | 在此元素获得逻辑焦点时发生 | |
MouseDown | 在指针位于此元素上并且按下任意鼠标按钮时发生。 | |
MouseMove | 在鼠标指针位于此元素上并且移动鼠标指针时发生。 | |
Click | 控件的点击事件 |
内容控件、文本控件、条目控件、布局控件、其它控件
内容控件 (System.Windows.Controls.ContentControl) |
||
---|---|---|
System.Windows.Controls.Label | ||
System.Windows.Controls.TextBlock | 继承自FrameworkElement类 | |
System.Windows.Controls.Button | ||
System.Windows.Controls.Border | 继承自Decorator类 | |
System.Windows.Controls.RadioButton | ||
System.Windows.Controls.CheckBox | ||
System.Windows.Controls.ToolTip | ||
System.Windows.Controls.GroupBox | ||
System.Windows.Controls.Expander | ||
System.Windows.Controls.Frame |
文本控件 (System.Windows.Controls.TextBoxBase) |
||
---|---|---|
System.Windows.Controls.TextBox | ||
System.Windows.Controls.RichTextBox |
条目控件 (System.Windows.Controls.ItemsControl) |
||
---|---|---|
System.Windows.Controls.ComboBox | ||
System.Windows.Controls.Menu | ||
System.Windows.Controls.ContextMenu | ||
System.Windows.Controls.TabControl | ||
System.Windows.Controls.ToolBar | ||
System.Windows.Controls.ToolBarTray | ||
System.Windows.Controls.ListBox | ||
System.Windows.Controls.DataGrid | ||
System.Windows.Controls.TreeView |
布局控件 (System.Windows.Controls.Panel) |
||
---|---|---|
System.Windows.Controls.Grid | ||
System.Windows.Controls.StackPanel | ||
System.Windows.Controls.DockPanel | ||
System.Windows.Controls.WrapPanel | ||
System.Windows.Controls.Canvas |
其他控件 | ||
---|---|---|
System.Windows.Controls.Calendar | ||
System.Windows.Controls.Image | ||
System.Windows.Controls.ProgressBar | ||
System.Windows.Shapes.Rectangle |
using Ken.Wpf.Entity;
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Media;
namespace Ken.Wpf.Utils
{
public class MenuHelper
{
public static List<MenuInfo> CreateMenus()
{
List<MenuInfo> menus = new List<MenuInfo>();
MenuInfo m1 = new MenuInfo("出入库管理",null);
MenuInfo m2 = new MenuInfo("请假管理", null);
MenuInfo m3 = new MenuInfo("考勤管理",null);
MenuInfo m3_1 = new MenuInfo("日报管理", m3);
MenuInfo m3_2 = new MenuInfo("请假管理", m3);
MenuInfo m4 = new MenuInfo("商品管理",null);
MenuInfo m4_1 = new MenuInfo("单位管理", m4);
MenuInfo m4_2 = new MenuInfo("类别管理", m4);
menus.Add(m1);
menus.Add(m2);
menus.Add(m3);
menus.Add(m4);
return menus;
}
}
}
<Label Width="180" Height="30" Content="我是个label控件"
HorizontalAlignment="Right"
VerticalAlignment="Top" Margin="0,10" FontSize="18" Foreground="Blue"/>
<TextBlock Text="我是个TextBlock33" FontSize="30" FontWeight="Light" Foreground="Red">
我是文本一<LineBreak/>
我是文本二<LineBreak/>
我是文本三
TextBlock>
<Button Width="100" Height="30" HorizontalAlignment="Left" VerticalAlignment="Top"
Content="我是个按钮" Margin="20,20,0,0" Background="Teal"
BorderThickness="5,0,10,0" BorderBrush="Transparent" Foreground="White"
Click="Button_Click_1" MouseMove="Button_MouseMove"
>
<Border Width="200" Height="80" Background="LightBlue"
BorderBrush="Red" BorderThickness="1,1,2,1" CornerRadius="15">
<Button Background="Transparent" FontSize="20" Foreground="White"
Content="我是个按钮" Click="Button_Click" BorderBrush="Transparent">
Button>
Border>
<RadioButton Content="男" GroupName="sex" Margin="10,100" FontSize="20" Foreground="red" VerticalAlignment="Top" HorizontalAlignment="Left" >RadioButton>
<RadioButton Content="女" GroupName="sex" Margin="80,100" FontSize="20" Foreground="red" VerticalAlignment="Top" HorizontalAlignment="Left" >RadioButton>
<RadioButton Content="语文" GroupName="course" FontSize="20" Foreground="Blue" VerticalAlignment="Top" HorizontalAlignment="Left" >RadioButton>
<RadioButton Content="数学" GroupName="course" Margin="70,0" FontSize="20" Foreground="Blue" VerticalAlignment="Top" HorizontalAlignment="Left" >RadioButton>
<RadioButton Content="历史" GroupName="course" Margin="140,0" FontSize="20" Foreground="Blue" VerticalAlignment="Top" HorizontalAlignment="Left" >RadioButton>
<RadioButton Content="外语" GroupName="course" Margin="210,0" FontSize="20" Foreground="Blue" VerticalAlignment="Top" HorizontalAlignment="Left" >RadioButton>
CheckBox演示效果
<Grid Name="gridMain">
<Label VerticalAlignment="Top" Width="120" FontSize="20" Background="Orange" Foreground="White">我的选课:Label>
<CheckBox Content="C语言" Margin="300,50" VerticalAlignment="Top"
HorizontalAlignment="Left" Width="120" Height="30" FontSize="18" BorderBrush="blue">CheckBox>
<CheckBox Content="计算机组成原理" Margin="300,80" VerticalAlignment="Top"
HorizontalAlignment="Left" Width="150" Height="30" FontSize="18" IsChecked="True">CheckBox>
<CheckBox Content="计算机网络" Margin="300,110" VerticalAlignment="Top"
HorizontalAlignment="Left" Width="120" Height="30" FontSize="18">CheckBox>
<Button Content="获取我的选课"
Width="120" Height="30" Click="Button_Click"
HorizontalAlignment="Left" Margin="331,182,0,0" VerticalAlignment="Top"/>
Grid>
private void Button_Click(object sender, RoutedEventArgs e)
{
UIElementCollection children = gridMain.Children;
StringBuilder sbf = new StringBuilder("我的选课为:");
foreach (UIElement item in children)
{
if(item is CheckBox && (item as CheckBox).IsChecked.Value)
{
sbf.Append((item as CheckBox).Content+",");
}
}
MessageBox.Show(sbf.ToString());
}
<Label HorizontalAlignment="Left" FontSize="20">我是个label
<Label.ToolTip>
<ToolTip >
<Grid>
<TextBlock>1000000001.TextBlock>
<TextBlock>1000000002.TextBlock>
<TextBlock>1000000003.TextBlock>
Grid>
ToolTip>
Label.ToolTip>
Label>
<Button Width="180" Height="50" HorizontalAlignment="Left" FontSize="20" Margin="200,10">我是个button
<Button.ToolTip>
<TextBlock>Useful information goes here.TextBlock>
Button.ToolTip>
Button>
<Window x:Class="Ken.Wpf.Controls.WindowGroupBox"
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:local="clr-namespace:Ken.Wpf.Controls"
mc:Ignorable="d"
Title="WindowGroupBox" Height="450" Width="800">
<Window.Resources>
<ControlTemplate x:Key="myGroupBox" TargetType="GroupBox">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="40">RowDefinition>
<RowDefinition Height="*">RowDefinition>
Grid.RowDefinitions>
<Border Grid.Row="0" Background="Orange">
<Label Foreground="Red" FontWeight="Bold" FontSize="18">
我是个标题
Label>
Border>
<Border Grid.Row="1" Background="AliceBlue">
<StackPanel>
<TabControl Name="myTabControl"
TabStripPlacement="Top"
Margin="0, 0, 0, 10" Height="350"
>
<TabItem>
<TabItem.Header>_Job InfoTabItem.Header>
<StackPanel>
<TextBlock>Select a jobTextBlock>
<ListBox Name ="job" >
<ListBoxItem IsSelected="true">ProgrammerListBoxItem>
<ListBoxItem>TesterListBoxItem>
<ListBoxItem>WriterListBoxItem>
<ListBoxItem>ManagerListBoxItem>
ListBox>
StackPanel>
TabItem>
TabControl>
StackPanel>
Border>
Grid>
ControlTemplate>
Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*">RowDefinition>
<RowDefinition Height="*"> RowDefinition>
Grid.RowDefinitions>
<GroupBox Template="{StaticResource myGroupBox}" Grid.Row="0">
GroupBox>
<GroupBox Template="{StaticResource myGroupBox}" Grid.Row="1">
GroupBox>
Grid>
Window>
<Expander Header="折叠框" FontSize="18" Foreground="Blue" IsExpanded="True"
BorderThickness="1" BorderBrush="Green" ExpandDirection="Down"
VerticalAlignment="Top" HorizontalAlignment="Center" Height="100">
<StackPanel Orientation="Vertical">
<CheckBox FontSize="18">C#CheckBox>
<CheckBox FontSize="18">JAVACheckBox>
<CheckBox FontSize="18">C++CheckBox>
StackPanel>
Expander>
<Button Click="Button_Click" Content="调往百度" HorizontalAlignment="Left" Margin="230,27,0,0" VerticalAlignment="Top"/>
<Frame Name="myFrame" Source="https://fanyi.baidu.com/"
VerticalAlignment="Top" HorizontalAlignment="Center"
Width="700" Height="300" Margin="30,80" NavigationUIVisibility="Visible" LoadCompleted="myFrame_LoadCompleted">Frame>
private void Button_Click(object sender, RoutedEventArgs e)
{
//1.使用source
//this.myFrame.Source = new Uri("https://www.bilibili.com/", UriKind.Absolute);
//2.使用Navigate跳转
//使用 对象
//MyPage my = new MyPage();
//this.myFrame.Navigate(my);
//使用uri
//this.myFrame.Navigate(new Uri("https://www.bilibili.com/", UriKind.Absolute));
//3.使用Navigate跳转 携带参数
MyPage my = new MyPage();
this.myFrame.Navigate(my,"我是个参数");
}
private void myFrame_LoadCompleted(object sender, System.Windows.Navigation.NavigationEventArgs e)
{
object extraData = e.ExtraData;
Console.WriteLine(extraData);
}
<TextBox Name="myTextBox" FontSize="30" VerticalAlignment="Top"
HorizontalAlignment="Left" BorderBrush="Orange" SelectionBrush="Teal">
我是个文本控件
TextBox>
<Button Content="Button" HorizontalAlignment="Left" Margin="142,118,0,0" VerticalAlignment="Top" Height="51" Width="116" Click="Button_Click"/>
<RichTextBox Name="richTB">
<FlowDocument>
<Paragraph TextIndent="20">
将 HTML 内容粘贴到 RichTextBox 应用程序中可能会导致意外行为,因为 RichTextBox 使用 RTF 格式,而不是直接使用 HTML 格式。
文本始终换行 。
<LineBreak/>
RichTextBox 如果不希望文字换行,请将 PageWidth on FlowDocument 设置为大于宽度 RichTextBox。 但是,到达页面宽度后,文本仍会换行。
Paragraph>
<Paragraph>
<Run>Paragraph 2Run>
Paragraph>
<BlockUIContainer>
<StackPanel>
<Label>Paragraph 2Label>
<CheckBox>1112CheckBox>
StackPanel>
BlockUIContainer>
<Paragraph FontSize="50">
<Run>xRun>
<InlineUIContainer >
<Label Margin="-10,0,0,0" FontSize="30">4Label>
InlineUIContainer>
<Run>+Run>
<Run>yRun>
<InlineUIContainer >
<Label Margin="-10,0,0,0" FontSize="30">3Label>
InlineUIContainer>
<Run>=Run>
<Run>99Run>
Paragraph>
FlowDocument>
RichTextBox>
using Ken.Wpf.Entity;
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace Ken.Wpf.Controls
{
///
/// WindowComboBox.xaml 的交互逻辑
///
public partial class WindowComboBox : Window
{
public WindowComboBox()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
//1.使用items
/*this.comboBox1.Items.Add("C#");
this.comboBox1.Items.Add("Java");
this.comboBox1.Items.Add("Python");*/
//2.使用DataContext 进行绑定
List<ClassInfo> list = new List<ClassInfo>();
list.Add(new ClassInfo() { ClassName = "高三一班", Code = "301" });
list.Add(new ClassInfo() { ClassName = "高三二班", Code = "302" });
list.Add(new ClassInfo() { ClassName = "高三三班", Code = "303" });
/*this.comboBox1.DataContext = list;
this.comboBox1.DisplayMemberPath = "ClassName";
this.comboBox1.SelectedValuePath = "Code";*/
//3.使用ItemsSource 进行绑定
this.comboBox1.ItemsSource = list;
this.comboBox1.DisplayMemberPath = "ClassName";
this.comboBox1.SelectedValuePath = "Code";
}
private void Button_Click(object sender, RoutedEventArgs e)
{
List<ClassInfo> lists = this.comboBox1.ItemsSource as List<ClassInfo>;
lists.RemoveAt(0);
this.comboBox1.ItemsSource = null;
this.comboBox1.ItemsSource = lists;
}
}
}
------
namespace Ken.Wpf.Entity
{
class VacationSpots : ObservableCollection<string>
{
public VacationSpots()
{
Add("Spain");
Add("France");
Add("Peru");
Add("Mexico");
Add("Italy");
}
}
}
------
using System;
using System.Collections.Generic;
using System.Text;
namespace Ken.Wpf.Entity
{
public class ClassInfo
{
public string ClassName { get; set; }
public string Code { get; set; }
}
}
<ComboBox Name="comboBox1"
Text="My Cities"
IsEditable="True" ItemsSource="{Binding}"
IsReadOnly="False" Width="120" Height="30" VerticalAlignment="Top">
ComboBox>
<Button Click="Button_Click" Content="移除一项" HorizontalAlignment="Left" Margin="362,52,0,0" VerticalAlignment="Top"/>
<Window x:Class="Ken.Wpf.Controls.WindowMenu"
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:local="clr-namespace:Ken.Wpf.Controls"
mc:Ignorable="d"
Title="WindowMenu" Height="450" Width="800">
<Window.Resources>
<!--Control colors.-->
<Color x:Key="WindowColor">#FFE8EDF9</Color>
<Color x:Key="ContentAreaColorLight">#FFC5CBF9</Color>
<Color x:Key="ContentAreaColorDark">#FF7381F9</Color>
<Color x:Key="DisabledControlLightColor">#FFE8EDF9</Color>
<Color x:Key="DisabledControlDarkColor">#FFC5CBF9</Color>
<Color x:Key="DisabledForegroundColor">#FF888888</Color>
<Color x:Key="SelectedBackgroundColor">#FFC5CBF9</Color>
<Color x:Key="SelectedUnfocusedColor">#FFDDDDDD</Color>
<Color x:Key="ControlLightColor">White</Color>
<Color x:Key="ControlMediumColor">#FF7381F9</Color>
<Color x:Key="ControlDarkColor">#FF211AA9</Color>
<Color x:Key="ControlMouseOverColor">#FF3843C4</Color>
<Color x:Key="ControlPressedColor">#FF211AA9</Color>
<Color x:Key="GlyphColor">#FF444444</Color>
<Color x:Key="GlyphMouseOver">sc#1, 0.004391443, 0.002428215, 0.242281124</Color>
<!--Border colors-->
<Color x:Key="BorderLightColor">#FFCCCCCC</Color>
<Color x:Key="BorderMediumColor">#FF888888</Color>
<Color x:Key="BorderDarkColor">#FF444444</Color>
<Color x:Key="PressedBorderLightColor">#FF888888</Color>
<Color x:Key="PressedBorderDarkColor">#FF444444</Color>
<Color x:Key="DisabledBorderLightColor">#FFAAAAAA</Color>
<Color x:Key="DisabledBorderDarkColor">#FF888888</Color>
<Color x:Key="DefaultBorderBrushDarkColor">Black</Color>
<!--Control-specific resources.-->
<Color x:Key="HeaderTopColor">#FFC5CBF9</Color>
<Color x:Key="DatagridCurrentCellBorderColor">Black</Color>
<Color x:Key="SliderTrackDarkColor">#FFC5CBF9</Color>
<Color x:Key="NavButtonFrameColor">#FF3843C4</Color>
<LinearGradientBrush x:Key="MenuPopupBrush"
EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="0" />
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="0.5" />
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="ProgressBarIndicatorAnimatedFill"
StartPoint="0,0"
EndPoint="1,0">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="#000000FF"
Offset="0" />
<GradientStop Color="#600000FF"
Offset="0.4" />
<GradientStop Color="#600000FF"
Offset="0.6" />
<GradientStop Color="#000000FF"
Offset="1" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
<Style x:Key="{x:Type Menu}"
TargetType="{x:Type Menu}">
<Setter Property="OverridesDefaultStyle"
Value="True" />
<Setter Property="SnapsToDevicePixels"
Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Menu}">
<Border BorderThickness="1">
<Border.BorderBrush>
<LinearGradientBrush StartPoint="0,0"
EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="{DynamicResource BorderLightColor}"
Offset="0.0" />
<GradientStop Color="{DynamicResource BorderDarkColor}"
Offset="1.0" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Border.BorderBrush>
<Border.Background>
<LinearGradientBrush EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="0" />
<GradientStop Color="Teal"
Offset="1" />
</LinearGradientBrush>
</Border.Background>
<StackPanel ClipToBounds="True"
Orientation="Horizontal"
IsItemsHost="True" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!--1.使用路由UI对Command的设置-->
<RoutedUICommand x:Key="myCmd" ></RoutedUICommand>
</Window.Resources>
<!--2.使用命令绑定 CommandBind-->
<Window.CommandBindings>
<CommandBinding Command="{StaticResource myCmd}" Executed="CommandBinding_Executed"></CommandBinding>
</Window.CommandBindings>
<!--3.使用输入绑定 InputBinding-->
<Window.InputBindings>
<KeyBinding Command="{StaticResource myCmd}" Gesture="Ctrl+8" ></KeyBinding>
</Window.InputBindings>
<Grid>
<Menu Height="25" VerticalAlignment="Top" >
<MenuItem Header="出入库管理" Foreground="White" FontFamily="华文行楷" Height="21" Command="{StaticResource
myCmd}"/>
<MenuItem Header="请假管理" Foreground="White" FontFamily="华文行楷" Height="21"/>
<MenuItem Header="考勤管理" Foreground="White" FontFamily="华文行楷" Height="21"/>
<MenuItem Header="商品管理" Foreground="White" FontFamily="华文行楷" Height="21">
<MenuItem Header="单位管理" Foreground="Black" FontFamily="华文行楷" Height="21"></MenuItem>
<MenuItem Header="类别管理" Foreground="Black" FontFamily="华文行楷" Height="21" InputGestureText="Ctrl
+8"></MenuItem>
</MenuItem>
</Menu>
</Grid>
</Window>
private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
{
MessageBox.Show("Command!!!");
}
<Menu Name="menu1" VerticalAlignment="Top" Height="30" Background="Teal"
ItemsSource="{Binding}">
<Menu.ItemContainerStyle>
<Style TargetType="{x:Type MenuItem}">
"Command" Value="{Binding ICommand}">
Style>
Menu.ItemContainerStyle>
<Menu.ItemTemplate>
<HierarchicalDataTemplate DataType="{x:Type et:MenuInfo}" ItemsSource="{Binding SubMenus}">
<TextBlock Text="{Binding MenuName}">TextBlock>
HierarchicalDataTemplate>
Menu.ItemTemplate>
Menu>
Grid>
using Ken.Wpf.Commands;
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Input;
namespace Ken.Wpf.Entity
{
public class MenuInfo
{
///
/// 菜单名称
///
public string MenuName { get; set; }
///
/// 子菜单
///
public List<MenuInfo> SubMenus { get; set; }
///
/// Command
///
public ICommand ICommand { get {
return new MyCommand((o)=> {
MessageBox.Show(MenuName);
});
}
}
public MenuInfo(string menuName, MenuInfo parentMenu)
{
MenuName = menuName;
//将当期菜单挂载到父菜单下面
if (parentMenu != null)
{
List<MenuInfo> lists = parentMenu.SubMenus ?? new List<MenuInfo>();
lists.Add(this);
parentMenu.SubMenus = lists;
}
}
}
}
-------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Input;
namespace Ken.Wpf.Commands
{
///
/// 自定义实现ICommand
///
class MyCommand : ICommand
{
public event EventHandler CanExecuteChanged;
public Action<object> ExecuteAction;
public MyCommand(Action<object> executeAction)
{
ExecuteAction = executeAction;
}
public bool CanExecute(object parameter)
{
return true;
//throw new NotImplementedException();
}
public void Execute(object parameter)
{
if (this.ExecuteAction != null)
{
this.ExecuteAction(parameter);
}
}
}
}
<Label VerticalAlignment="Center" HorizontalAlignment="Center"
Content="我是Label" FontSize="30">
<Label.ContextMenu>
<ContextMenu Name="cm1" ItemsSource="{Binding}">
<ContextMenu.ItemContainerStyle>
<Style TargetType="{x:Type MenuItem}">
"Command" Value="{Binding ICommand}">
Style>
ContextMenu.ItemContainerStyle>
<ContextMenu.ItemTemplate>
<HierarchicalDataTemplate DataType="{x:Type et:MenuInfo}" ItemsSource="{Binding SubMenus}">
<TextBlock Text="{Binding MenuName}">TextBlock>
HierarchicalDataTemplate>
ContextMenu.ItemTemplate>
ContextMenu>
Label.ContextMenu>
Label>
private void Window_Loaded(object sender, RoutedEventArgs e)
{
//设置数据上下文
this.cm1.DataContext = MenuHelper.CreateMenus();
}
<TabControl>
<TabItem Header="tab1" FontSize="30">
<Grid>
<Label>我是tab1的内容Label>
<TextBox Name="textBox1" Width="50"/>
Grid>
TabItem>
<TabItem FontSize="30">
<TabItem.Header>
<Grid>
<Label> tab2Label>
Grid>
TabItem.Header>
<Label>我是tab2的内容Label>
TabItem>
<TabItem Header="tab3" FontSize="30">
<Label>我是tab3的内容Label>
TabItem>
TabControl>
<ToolBarTray Orientation="Horizontal" Margin="0,0,0,-115">
<ToolBar VerticalAlignment="Top" FontSize="30" Band="3" BandIndex="1">
<Label>
Label1
Label>
<Button>按钮1Button>
<Separator/>
<Button>按钮2Button>
<Button>按钮3Button>
<Separator/>
<Button>按钮4Button>
<Image Source="../Images/touxiang.jpg" Width="50" Height="50">Image>
ToolBar>
<ToolBar VerticalAlignment="Top" FontSize="30" Band="3" BandIndex="2" >
<Button>按钮1Button>
<Separator/>
<Button>按钮2Button>
<Button>按钮3Button>
ToolBar>
ToolBarTray>
private void Window_Loaded(object sender, RoutedEventArgs e)
{
//模拟数据
List<string> list = new List<string>();
list.Add("1001");
list.Add("1002");
list.Add("1003");
list.Add("1004");
this.listbox1.DataContext = list;
}
<ListBox Name="listbox1" FontSize="30" SelectionMode="Extended"
ItemsSource="{Binding}">
<ListBox.ItemTemplate>
<DataTemplate >
<TextBlock Text="{Binding}">TextBlock>
DataTemplate>
ListBox.ItemTemplate>
ListBox>
<DataGrid FontSize="30" Name="grid1" ItemsSource="{Binding}" AutoGenerateColumns="False"
CanUserAddRows="False" GridLinesVisibility="Vertical" >
<DataGrid.Columns>
<DataGridTextColumn Header="用户姓名" Binding="{Binding Name}">DataGridTextColumn>
<DataGridTextColumn Header="年龄" Binding="{Binding Age}">DataGridTextColumn>
<DataGridComboBoxColumn x:Name="depts" Header="部门" SelectedValueBinding="{Binding DeptId}">
DataGridComboBoxColumn>
<DataGridTemplateColumn>
<DataGridTemplateColumn.Header>
<TextBlock>列表4TextBlock>
DataGridTemplateColumn.Header>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}">TextBlock>
DataTemplate>
DataGridTemplateColumn.CellTemplate>
DataGridTemplateColumn>
DataGrid.Columns>
DataGrid>
private void Window_Loaded(object sender, RoutedEventArgs e)
{
//设置treeView1的数据上下文
this.treeView1.DataContext = MenuHelper.CreateMenus();
}
<TreeView FontSize="30" Name="treeView1" ItemsSource="{Binding}"
>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate DataType="{x:Type et:MenuInfo}" ItemsSource="{Binding SubMenus}">
<StackPanel Orientation="Horizontal">
<Image Source="../Images/touxiang.jpg" Width="50" Height="50">Image>
<TextBlock Text="{Binding MenuName}">TextBlock>
StackPanel>
HierarchicalDataTemplate>
TreeView.ItemTemplate>
TreeView>
<Grid ShowGridLines="True">
<!--自定义列-->
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200"></ColumnDefinition>
<ColumnDefinition Width="500"></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<!--自定义行-->
<Grid.RowDefinitions>
<RowDefinition Height="100"></RowDefinition>
<RowDefinition Height="200"></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<TextBlock Grid.Row="1" Grid.Column="0">我是TextBlock</TextBlock>
<TabControl Grid.Row="1" Grid.Column="1">
<TabItem Header="tab1"></TabItem>
<TabItem Header="tab2"></TabItem>
<TabItem Header="tab3"></TabItem>
</TabControl>
</Grid>
<StackPanel Orientation="Horizontal" Opacity="0.5">
<Label Width="180" Height="30" Content="我是个label控件"
VerticalAlignment="Top" Margin="0,10" FontSize="18" Foreground="Blue"/>
<Label Width="180" Height="30" Content="我是个label控件"
VerticalAlignment="Top" Margin="0,10" FontSize="18" Foreground="Blue"/>
<TextBlock>我是个TextBlockTextBlock>
<TabControl Grid.Row="1" Grid.Column="1">
<TabItem Header="tab1">TabItem>
<TabItem Header="tab2">TabItem>
<TabItem Header="tab3">TabItem>
TabControl>
StackPanel>
<DockPanel Background="Beige" LastChildFill="True">
<StackPanel DockPanel.Dock="Left" Background="Red" Width="50">StackPanel>
<StackPanel DockPanel.Dock="Top" Background="Black" Height="100">StackPanel>
<StackPanel DockPanel.Dock="Bottom" Background="Green" Height="100">StackPanel>
<StackPanel DockPanel.Dock="Right" Background="White" Width="100">StackPanel>
<DockPanel DockPanel.Dock="Right" Background="Purple" LastChildFill="False" >
DockPanel>
DockPanel>
<WrapPanel Width="700" Orientation="Vertical">
<StackPanel Width="300" Height="100" Background="Teal">StackPanel>
<StackPanel Width="300" Height="100" Background="Teal" Orientation="Vertical">
<Label FontSize="20">按从左到右的顺序位置定位子元素Label>
<Label FontSize="20">,在包含框的边缘处将内容切换到下一行。Label>
StackPanel>
<StackPanel Width="300" Height="100" Background="Red">
StackPanel>
WrapPanel>
![image.png](https://img-blog.csdnimg.cn/img_convert/91cc3372c046078312a8591b2c622129.png#clientId=u8d18fe6b-f2a3-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=311&id=u66694834&margin=[object Object]&name=image.png&originHeight=311&originWidth=357&originalType=binary&ratio=1&rotation=0&showTitle=false&size=2016&status=done&style=none&taskId=u3b918b94-129b-4fd3-9a86-add4d43f511&title=&width=357)
<Canvas Width="500" Height="500" >
<StackPanel Width="100" Height="100" Background="Red" Canvas.Top="50" Canvas.Left="200">StackPanel>
<StackPanel Width="100" Height="100" Background="Green" Canvas.Top="250" Canvas.Left="200">StackPanel>
<StackPanel Width="100" Height="100" Background="Yellow" Canvas.Top="150" Canvas.Left="95">StackPanel>
<WrapPanel Width="100" Height="100" Background="Black" Canvas.Top="150" Canvas.Left="305">WrapPanel>
<WrapPanel Width="100" Height="100" Background="Purple" Canvas.Bottom="80" Canvas.Right="80">WrapPanel>
Canvas>
<Calendar SelectionMode="MultipleRange" DisplayDate="2022-01-01" SelectedDate="2022-01-01"
DisplayDateStart="2022-01-01" DisplayDateEnd="2022-03-01">
Calendar>
<TextBlock Background="Orange" Width="300" Height="80" FontSize="60pt"
FontFamily="华文行楷" TextAlignment="Center" VerticalAlignment="Center">
<TextBlock.Foreground>
<ImageBrush ImageSource="../Images/avatar.png" TileMode="FlipX" Viewport="0,0,30,30" ViewportUnits="Absolute">
ImageBrush>
TextBlock.Foreground>
Text
TextBlock>
<ProgressBar Width="300" Height="50"
Name="progressBar1">
<ProgressBar.Triggers>
<EventTrigger RoutedEvent="ProgressBar.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="progressBar1"
Storyboard.TargetProperty="Value"
From="0" To="100" Duration="1:1:5" />
Storyboard>
BeginStoryboard>
EventTrigger>
ProgressBar.Triggers>
ProgressBar>
<Rectangle Stroke="Green" HorizontalAlignment ="Left" VerticalAlignment="Center"
StrokeDashArray="2" RadiusX="200" RadiusY="200" StrokeThickness="20" Width="400" Height="400" Margin="20,0">
<Rectangle.Fill>
<DrawingBrush>
<DrawingBrush.Drawing>
<ImageDrawing ImageSource="../Images/avatar.png" Rect="0,0,200,200">ImageDrawing>
DrawingBrush.Drawing>
DrawingBrush>
Rectangle.Fill>
Rectangle>
WPF 还包括增强属性和事件的其他编程构造: 依赖项属性 和 路由事件。
依赖性示例:
<DockPanel>
<Button Background="{DynamicResource MyBrush}" Content="I am gold" Width="200px" Height=" 30px" />
<DockPanel.Resources>
<SolidColorBrush x:Key="MyBrush" Color="Gold" />
DockPanel.Resources>
DockPanel>
路由事件:
(路由是指网络数据包发送到目的地址的路线)
<StackPanel>
<StackPanel.Resources>
<Style TargetType="{x:Type Button}">
"Click" Handler="SetColor"/>
Style>
StackPanel.Resources>
<Button>Click meButton>
<Button Name="ThisButton" Click="HandleThis">
Raise event, handle it, use handled=true handler to get it anyway.
Button>
StackPanel>
private void SetColor(object sender, RoutedEventArgs e)
{
MessageBox.Show("点击了按钮:"+(e.OriginalSource is Button));
}
private void HandleThis(object sender, RoutedEventArgs e)
{
MessageBox.Show("点击了按钮:");
}
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="MyNamespace.MyCanvasCodeInline"
>
<Button Name="button1" Click="Clicked">Click Me!</Button>
<x:Code><![CDATA[
void Clicked(object sender, RoutedEventArgs e)
{
button1.Content = "Hello World";
}
]]></x:Code>
</Page>
将属性值延迟为数据绑定值,从而创建中间表达式对象并解释应用于元素及其绑定的数据上下文。
<object property="{Binding}" .../>
<object property="{Binding bindProp1=value1[, bindPropN=valueN]*}" ... />
<object property="{Binding path}" .../>
<object property="{Binding path[, bindPropN=valueN]*}" .../>
在这些语法中, 和 []* 不是文本。 它们是表示法的一部分,用于指示可以使用零个或多个 bindPropvalue=, 对,并且它们与前面的 bindPropvalue= 对之间具有分隔符。
可以改为使用对象元素的属性设置"可以使用绑定扩展设置的绑定属性"部分中列出的任何 Binding 属性。 但是,这不是 真正的标记扩展用法 Binding,它只是设置 CLR 类属性的属性的常规 XAML Binding 处理。 换句话说,
属性 | 作用 |
---|---|
StaticResource | 通过查找对已定义的资源的引用,为任何 XAML 属性属性提供值。 |
DynamicResource | 通过将任何 XAML 属性属性的值延迟为对已定义资源的引用,为该属性提供值。 |
RelativeSource | 指定绑定源的属性 RelativeSource ,以便在 绑定标记扩展中使用,或在设置 RelativeSource 在 XAML 中建立的元素的属性 Binding 时使用。 |
TemplateBinding | 连接某一控件模板中的属性值,使之成为模板化控件上另一个属性的值。 |
ThemeDictionary | 为集成第三方控件的自定义控件创作者或应用程序提供一种方法,用于加载要在设置控件样式时使用的特定于主题的资源字典。 |
ColorConvertedBitmap | 提供一种方法,用于指定没有嵌入的配置文件的位图源。 颜色上下文/配置文件由 URI 指定,与映像源 URI 相同。 |
官方文档:https://docs.microsoft.com/zh-cn/dotnet/desktop/wpf/data/?view=netdesktop-6.0
前面部分中讨论的一些概念可以重申为:使用 Binding 对象建立绑定,且每个绑定通常具有四个组件:绑定目标、目标属性、绑定源以及指向要使用的源值的路径。
绑定源绑定到元素的活动 DataContext。 如果元素没有显式定义 DataContext,则会自动继承。
请考虑以下示例,其中的绑定源对象是一个名为 MyData 的类,该类在** Ken.Wpf.Entity**命名空间中定义。 出于演示目的,MyData 具有名为 ColorName 的字符串属性,其值设置为“Red”。 因此,此示例生成一个具有红色背景的按钮。
<Window x:Class="Ken.Wpf.MainWindow"
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:local="clr-namespace:Ken.Wpf"
xmlns:c="clr-namespace:Ken.Wpf.Entity"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid >
<Grid.Resources>
<c:MyData x:Key="myDataSource"/>
Grid.Resources>
<Grid.DataContext>
<Binding Source="{StaticResource myDataSource}"/>
Grid.DataContext>
<Button Background="{Binding Path=ColorName}"
Width="150" Height="30">
I am bound to be RED!
Button>
Grid>
Window>
以下示例在自定义控件 CustomButton 库中实现 类。 派生 CustomButton 自 的 类 Button:
public class CustomButton : Button
{
// Register a custom routed event using the Bubble routing strategy.
public static readonly RoutedEvent ConditionalClickEvent = EventManager.RegisterRoutedEvent(
name: "ConditionalClick",
routingStrategy: RoutingStrategy.Bubble,
handlerType: typeof(RoutedEventHandler),
ownerType: typeof(CustomButton));
// Provide CLR accessors for assigning an event handler.
public event RoutedEventHandler ConditionalClick
{
add { AddHandler(ConditionalClickEvent, value); }
remove { RemoveHandler(ConditionalClickEvent, value); }
}
void RaiseCustomRoutedEvent()
{
// Create a RoutedEventArgs instance.
RoutedEventArgs routedEventArgs = new(routedEvent: ConditionalClickEvent);
// Raise the event, which will bubble up through the element tree.
RaiseEvent(routedEventArgs);
}
// For demo purposes, we use the Click event as a trigger.
protected override void OnClick()
{
// Some condition combined with the Click event will trigger the ConditionalClick event.
if (DateTime.Now > new DateTime())
RaiseCustomRoutedEvent();
// Call the base class OnClick() method so Click event subscribers are notified.
base.OnClick();
}
}
该示例包括一个单独的 WPF 应用程序,该应用程序使用 XAML CustomButtonStackPanel标记将 的实例添加到 ,Handler_ConditionalClickConditionalClick并将 方法分配为 和 元素StackPanel1的事件CustomButton处理程序。
<Window x:Class="CodeSample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:custom="clr-namespace:WpfControl;assembly=WpfControlLibrary"
Title="How to create a custom routed event" Height="100" Width="300">
<StackPanel Name="StackPanel1" custom:CustomButton.ConditionalClick="Handler_ConditionalClick">
<custom:CustomButton
Name="customButton"
ConditionalClick="Handler_ConditionalClick"
Content="Click to trigger a custom routed event"
Background="LightGray">
custom:CustomButton>
StackPanel>
Window>
在代码隐藏中,WPF 应用程序定义事件 Handler_ConditionalClick 处理程序方法。 只能在代码隐藏中实现事件处理程序方法。
// The ConditionalClick event handler.
private void Handler_ConditionalClick(object sender, RoutedEventArgs e)
{
string senderName = ((FrameworkElement)sender).Name;
string sourceName = ((FrameworkElement)e.Source).Name;
Debug.WriteLine($"Routed event handler attached to {senderName}, " +
$"triggered by the ConditionalClick routed event raised on {sourceName}.");
}
// Debug output when CustomButton is clicked:
// Routed event handler attached to CustomButton,
// triggered by the ConditionalClick routed event raised on CustomButton.
// Routed event handler attached to StackPanel1,
// triggered by the ConditionalClick routed event raised on CustomButton.
单击 CustomButton 时:
事件 Handler_ConditionalClick 处理程序获取有关触发它的事件的以下信息:
备注
路由事件和 CLR 事件之间的主要区别在于路由事件遍历元素树,查找处理程序,而 CLR 事件不遍历元素树,处理程序只能附加到引发事件的源对象。 因此,路由事件 sender 可以是元素树中任何遍历的元素。
可以像冒泡事件一样创建隧道事件,只不过你将在事件注册调用中将路由策略设置为 Tunnel。 有关隧道事件详细信息,请参阅 WPF 输入事件。