WPF基础篇

第一章 窗体的基本属性

SizeToContent
Icon
WindowStartupLocation
MaxWidth   MinWidth
Topmost

<Window x:Class="zhaoxi.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:zhaoxi"
        mc:Ignorable="d"
        SizeToContent="Manual" 
        WindowStartupLocation="CenterScreen"
        Icon="image/logo.ico"
        
    Title="MainWindow" Height="450" Width="800" MaxWidth="1200" MinWidth="500">
    <!-- SizeToContent="WidthAndHeight"  默认窗体大小随内容宽高 -->
    <!-- Icon="image/logo.ico" 窗体的图标设置(右键图片属性:生产操作:资源)-->
    <!-- 应用程序的图标:右键项目属性 >> 应用程序 >> win32资源 >> 图标(需要icon文件) -->
    <!--  WindowStartupLocation="CenterScreen" 窗体启动位置-->
    <!--  MaxWidth="1200" MinWidth="500" 最大宽高和最小宽-->
    <Grid>
        <Button Content="点击打开新窗口" Width="100" Height="20" x:Name="btn" Click="btn_Click"></Button>
        <!-- x:Name="btn" 
            定义了一个名为 btn 的标识符,它对应于这个 <Button> 元素。
            在代码后面(例如C#代码中),你可以使用 btn 这个名字来直接访问这个按钮,进行诸如改变它的 Content、Width、Height 属性或添加点击事件处理器等操作。
        -->
        <!-- Click="btn_Click" 点击事件-->
    </Grid>
</Window>

子窗体打开在父窗体正中间

using chapter1;
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.Navigation;
using System.Windows.Shapes;

namespace zhaoxi
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 点击打开子窗体事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_Click(object sender, RoutedEventArgs e)
        {
            Window1 window1 = new Window1();
            window1.Owner = this; //窗体的所有者是当前主窗体
            window1.Show();
        }
    }
}

子窗体 Window1

<Window x:Class="chapter1.Window1"
        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:chapter1"
        mc:Ignorable="d"
        WindowStartupLocation="CenterScreen"
        Topmost="True"
        Title="Window1" Height="250" Width="400">
        
    <Grid>
        <Button Content="只是一个新窗口" Width="200" Height="50" FontSize="20"/>
    </Grid>
</Window>

效果

 第二章 布局控件

Grid
<Window x:Class="chapter2.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:chapter2"
        mc:Ignorable="d"
        Title="Grid学习" Height="450" Width="800">
    <!-- 默认一行一列-->
    <Grid>
        <!--- 行定义 -->
        <Grid.RowDefinitions>
            <!-- 宽高 * 百分比 -->
            <RowDefinition Height="1*"></RowDefinition>
            <RowDefinition Height="2*"></RowDefinition>
            <RowDefinition Height="100"></RowDefinition>
        </Grid.RowDefinitions>
        
        <!-- 列定义 -->
        <Grid.ColumnDefinitions>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
        </Grid.ColumnDefinitions>
        
        <!---默认是第一个(从0开始)-->
        <Button Grid.Row="0" Content="按钮1" Width="100" Height="20"></Button>
        <Button Grid.Row="1" Grid.Column="1" Content="按钮2" Width="100" Height="20"></Button>
        <!-- 行列合并 -->
        <Button Grid.Row="2" Grid.ColumnSpan="3" Content="按钮3" Width="100" Height="20"></Button>
    </Grid>
</Window>

效果

 GridSplitter
<Window x:Class="chapter2.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:chapter2"
        mc:Ignorable="d"
        Title="GridSplitter" Height="450" Width="800">
    <Grid>
        <!--- 列定义 -->
        <Grid.ColumnDefinitions>
            <!-- 宽高 * 百分比 -->
            <ColumnDefinition Width="1*"></ColumnDefinition>
            <ColumnDefinition Width="auto"></ColumnDefinition>
            <ColumnDefinition Width="2*"></ColumnDefinition>
        </Grid.ColumnDefinitions>

        <TextBlock FontSize="20" Foreground="Red" Background="Blue" TextWrapping="Wrap">这是第一列的内容,是不是很多呢?哈哈哈,textwarping自动换行!</TextBlock>
        <TextBlock Grid.Column="2" FontSize="20" Foreground="blue" Background="red">这是第三列的内容</TextBlock>
        <!-- GridSplitter 分割线,动态调整区域大小。 ShowsPreview 显示预览效果,默认值false-->
        <GridSplitter HorizontalAlignment="Center" ShowsPreview="False" Grid.Column="1" Width="10" Background="green"></GridSplitter>
   
    </Grid>
</Window>

效果

StackPanel

功能:将子元素按照一个方向(垂直或水平)堆叠排列。
属性:
Orientation: 决定子元素的排列方向,默认为垂直(Vertical)。也可以设置为水平(Horizontal)。
适用场景:适合需要简单线性排列的场景,比如菜单项列表、表单项等。

<StackPanel Orientation="Vertical">
    <Button Content="按钮1"/>
    <Button Content="按钮2"/>
    <Button Content="按钮3"/>
</StackPanel>
WrapPanel

功能:将子元素按指定的方向排列,并在空间不足时自动换行。
属性:
Orientation: 同样可以决定子元素的排列方向,支持垂直(Vertical)和水平(Horizontal)。
适用场景:当您希望UI元素能够根据可用空间自动调整布局时非常有用,例如标签云、工具栏中的图标等。

<WrapPanel Orientation="Horizontal">
    <Button Content="按钮1"/>
    <Button Content="按钮2"/>
    <Button Content="按钮3"/>
    <!-- 更多按钮 -->
</WrapPanel>
DockPanel

功能:允许子元素停靠在其内部的边缘(上、下、左、右)或居中。
属性:
LastChildFill: 默认值为True,表示最后一个子元素是否应该填充剩余的空间。
适用场景:非常适合构建具有边框或包含多个区域的应用程序框架,如带有顶部导航栏、侧边栏和内容区域的主窗口布局。

<DockPanel LastChildFill="True">
    <Button DockPanel.Dock="Top" Content="顶部"/>
    <Button DockPanel.Dock="Left" Content="左侧"/>
    <Button Content="填充其余部分"/>
</DockPanel>
 UniformGrid

主要特点
  固定单元格大小:在 UniformGrid 中,所有的单元格大小是相等的,这使得它非常适合用于需要均匀分布元素的场景。
  自动排列子元素:子元素会按照从左到右、从上到下的顺序依次填入单元格中,不需要显式地指定每个元素的位置。
  行列自适应:可以根据添加的子元素数量自动调整行数和列数,或者你可以通过设置属性来手动控制行数和列数。
常用属性
  Rows 和 Columns:可以用来指定网格的行数和列数。如果未指定,则根据子元素的数量自动决定。
  FirstColumn:确定从哪一列开始填充子元素,允许你跳过网格中的某些列。

<Window x:Class="chapter2.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:chapter2"
        mc:Ignorable="d"
        Title="StackPanel" Height="450" Width="800">
    
    <UniformGrid Rows="3" Columns="3" FirstColumn="1">
        <Button Content="按钮1"/>
        <Button Content="按钮2"/>
        <Button Content="按钮3"/>
        <Button Content="按钮4"/>
        <Button Content="按钮5"/>
        <Button Content="按钮6"/>
        <Button Content="按钮7"/>
        <Button Content="按钮8"/>
        <Button Content="按钮9"/>
    </UniformGrid>
</Window>

效果

Canvas

  是一种布局控件,它允许你通过精确的坐标来定位子元素。这意味着你可以指定每个子元素的 Left、Top、Right 和 Bottom 属性,以确定它们在 Canvas 内的具体位置。这种灵活性使得 Canvas 非常适合创建自定义布局和图形界面。

主要特点
  绝对定位:Canvas 使用绝对坐标系统来定位其子元素。你可以通过设置 Canvas.Left 和 Canvas.Top 附加属性(也可以使用 Canvas.Right 和 Canvas.Bottom)来指定子元素的位置。
  固定大小:默认情况下,Canvas 不会自动调整其大小以适应其内容。你需要手动设定 Canvas 的宽度和高度,或者让它的大小由外部容器决定。
  适合自由布局:由于其基于坐标的定位方式,Canvas 特别适合用于需要精确控制元素位置的场景,比如绘制图表、游戏界面等。
常用属性
  Canvas.Left: 设置子元素左边距离 Canvas 左边缘的距离。
  Canvas.Top: 设置子元素顶部距离 Canvas 上边缘的距离。
  Canvas.Right: 设置子元素右边距离 Canvas 右边缘的距离。
  Canvas.Bottom: 设置子元素底部距离 Canvas 下边缘的距离。
  Background: 设置 Canvas 背景颜色或图案。

<Window x:Class="chapter2.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:chapter2"
        mc:Ignorable="d"
        Title="Canvas" Height="450" Width="800">
    <!-- 画布坐标-->
    <!--Panel.ZIndex="1" 元素顺序-->
    <Canvas>
        <Button Canvas.Top="20" Canvas.Left="200" Content="按钮1" Width="50" Height="20"></Button>
        <Button Canvas.Top="60" Panel.ZIndex="1" Content="按钮2" Width="50" Height="20"></Button>
        <Button Canvas.Top="120" Content="按钮3" Width="50" Height="20"></Button>
        <Button Canvas.Top="200" Content="按钮4" Width="50" Height="20"></Button>
        <Button Canvas.Top="250" Content="按钮5" Width="50" Height="20"></Button>
        <Button Canvas.Bottom="20" Content="按钮6" Width="50" Height="20"></Button>
    </Canvas>
</Window>

效果

 第三章  依赖属性和附加属性

1. 依赖属性(Dependency Property

定义
  依赖属性是 WPF 属性系统的核心,用于扩展传统的 .NET 属性。

  它允许属性支持数据绑定、动画、样式、资源引用等高级功能。

特点
  属性值继承:依赖属性可以从父元素继承值。

  默认值支持:可以为依赖属性设置默认值。

  属性值优先级:依赖属性的值可以通过多种方式设置(如本地值、样式、模板等),并且有明确的优先级规则。

  数据绑定支持:依赖属性可以直接绑定到其他属性或数据源。

  资源引用:依赖属性可以引用静态资源或动态资源。

使用场景
  用于自定义控件或扩展现有控件的属性。

  需要支持数据绑定、动画、样式等功能的属性。

<Window x:Class="chapter3.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:chapter3"
        mc:Ignorable="d"
        Title="附加属性" Height="450" Width="800">
    <Grid>
        <local:MyCustomControl Text="依赖属性" MyCustom="111" Height="50" Width="200" TextAlignment="Center" ></local:MyCustomControl>
    </Grid>
</Window>

MyCustomControl.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;

namespace chapter3
{
    /// <summary>
    /// 依赖属性
    /// 三步骤:定义、注册、包装
    /// </summary>
    public class MyCustomControl : TextBox
    {
        // 注册依赖属性 快捷键  propdp
        public static readonly DependencyProperty MyCustomProperty = DependencyProperty.Register(
            "MyCustom", //属性名 
            typeof(string), //数据类型
            typeof(MyCustomControl),//类型,改属性属于哪一个类型
            //OnMyCustomPropertyChanged 属性改变回调函数,coerceValueCallback 强制回调函数
            new PropertyMetadata("默认值", OnMyCustomPropertyChanged,coerceValueCallback),
            new ValidateValueCallback(ValidationData));//验证函数

        

        // 属性CLR包装器
        public string MyCustom
        {
            get { return (string)GetValue(MyCustomProperty); }
            set { SetValue(MyCustomProperty, value); }
        }

        /// <summary>
        /// 属性改变回调函数
        /// </summary>
        /// <param name="d"></param>
        /// <param name="e"></param>        
        private static void OnMyCustomPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            // 处理属性变化
            MessageBox.Show($"{MyCustomProperty}发生了变化!");
        }

        /// <summary>
        /// 强制回调函数
        /// </summary>
        /// <param name="d"></param>
        /// <param name="baseValue"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        private static object coerceValueCallback(DependencyObject d, object baseValue)
        {
            string data = (string)baseValue;
            if (data == null) 
            {
                MessageBox.Show($"强制回调222!{data}");
                return "222";
            }
            MessageBox.Show($"强制回调333!{data}");
            return "333";

        }

        /// <summary>
        /// 验证函数
        /// </summary>
        /// <param name="value"></param>
        /// <returns>true|false 验证不通过会报错</returns>
        /// <exception cref="NotImplementedException"></exception>
        private static bool ValidationData(object value)
        {
            string data = (string)value;
            if (data != null)
            {
                MessageBox.Show($"验证true{data}");
                return true;
            }
            MessageBox.Show($"验证false{data}");
            return false;
        }
    }
}

执行顺序:验证>>赋值>>强制回调>>属性改变回调 (验证函数值没改变一次调用一次)

2. 附加属性(Attached Property

定义
  附加属性是一种特殊的依赖属性,它允许一个对象为另一个对象定义属性。

  附加属性通常用于布局控件(如 Grid、Canvas)或行为(如 ToolTipService)。

特点
  属性附加到其他对象:附加属性可以“附加”到任何对象上,即使该对象本身没有定义该属性。

  灵活性高:附加属性可以扩展现有控件的功能,而无需修改控件本身。

  常用于布局:例如,Grid.Row 和 Grid.Column 是附加属性,用于定义子元素在 Grid 中的位置。

使用场景
  用于布局控件(如 Grid、Canvas)。

  用于扩展现有控件的功能(如 ToolTipService.ToolTip)。

public class MyAttachedProperties
{
    // 定义附加属性
    public static readonly DependencyProperty IsEnabledProperty =
        DependencyProperty.RegisterAttached(
            "IsEnabled",
            typeof(bool),
            typeof(MyAttachedProperties),
            new PropertyMetadata(false));

    // Get 方法
    public static bool GetIsEnabled(DependencyObject obj)
    {
        return (bool)obj.GetValue(IsEnabledProperty);
    }

    // Set 方法
    public static void SetIsEnabled(DependencyObject obj, bool value)
    {
        obj.SetValue(IsEnabledProperty, value);
    }
}

在 XAML 中使用附加属性:

<Button local:MyAttachedProperties.IsEnabled="True" Content="Click Me" />
3. 依赖属性与附加属性的区别

总结

  • 依赖属性:用于扩展控件属性,支持数据绑定、动画、样式等功能。

  • 附加属性:用于为其他对象定义属性,常用于布局控件或扩展功能。

 

第四章 事件

事件是用户交互和应用程序逻辑的重要组成部分。WPF 的事件系统基于 .NET 的事件模型,但提供了更强大的功能,如 路由事件(Routed Events) 和 附加事件(Attached Events)

1 路由事件(Routed Events)

定义:路由事件是一种特殊的事件,它可以在元素树中向上(冒泡)或向下(隧道)传播。

传播方式:

  冒泡事件(Bubbling):从事件源元素向上传播到根元素。

  隧道事件(Tunneling):从根元素向下传播到事件源元素,一般以Prerview开头。

  直接事件(Direct):仅在事件源元素上触发,不传播。

典型示例:

  Button.Click 是一个冒泡事件。

  PreviewMouseDown 是一个隧道事件。

2. 附加事件(Attached Events)

定义:附加事件是一种特殊的路由事件,它可以在没有定义该事件的类上使用。

典型示例:

  Mouse.MouseDown 是一个附加事件,可以在任何元素上使用。

3.事件处理程序

定义:事件处理程序是响应事件的代码逻辑。

注册方式:

  在 XAML 中直接绑定:

<Button Click="Button_Click" Content="Click Me" />

  在代码中动态注册:

button.Click += Button_Click;
4.WPF 事件的类型

输入事件
  鼠标事件:MouseDown、MouseUp、MouseMove、MouseEnter、MouseLeave 等。
  键盘事件:KeyDown、KeyUp、TextInput 等。
  触摸事件:TouchDown、TouchMove、TouchUp 等。

5.生命周期事件

控件加载和卸载:
  Loaded、Unloaded。

控件初始化:
  Initialized。

5.布局和渲染事件

  布局事件:LayoutUpdated。

  渲染事件:Render。

6.数据绑定事件

  数据更改事件:DataContextChanged、SourceUpdated、TargetUpdated。

7. 事件处理

事件处理程序可以通过 e.Handled = true 标记事件为已处理,阻止事件继续传播(冒泡和隧道事件)。

8.事件源

通过 e.Source 获取事件的原始触发元素。
通过 e.OriginalSource 获取事件的原始源(通常是具体的子元素)。

posted @ 2025-02-25 16:41  别动我的猫  阅读(2)  评论(0编辑  收藏  举报