WPF教程

基础界面解释

<Window x:Class="WpfApp1.MainWindow"
		<!--引入一组名称空间-->
		<!--控件&&布局相关-->
		<!--默认的名称空间,无需再取名字-->
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        <!--编译器相关,其中"x"就是映射过来的"名称空间"-->
        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:WpfApp1"
        mc:Ignorable="d"
        <!--Window对象的属性-->
        Title="MainWindow" Height="450" Width="800">
    <Grid>

    </Grid>
</Window>

  • 解释说明
- 把Window,Grid当成对象
	- 既然是对象,就有属性和字段来描述它

WPF绘制的形式

  • 使用KeyValue的形式
 <Grid>
 	<!--绘制矩形-->
     <!--<Rectangle Height="80" Width="200" Stroke="Black" Fill="Blue" />-->
     <!--绘制三角形-->
     <!--<Path Data="M 0,0 L 200,100 L 100,200 Z" Stroke="Black"  Fill="Red"/>-->
 </Grid>
  • 实例演示: WPF中使用自定义类作为资源的基本用法
// MainWindow.xaml

<Window x:Class="WpfApp1.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"
        <!--引入主窗体的代码逻辑的名称空间,映射并命名为"local"-->
        xmlns:local="clr-namespace:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800" WindowStartupLocation="CenterScreen">

    <Window.Resources>
    	<!-- 在窗口级资源字典中创建Human实例 -->
        <local:Human x:Key="human" Name="Tim" />
    </Window.Resources>
    <Grid>
    	<!--绘制按钮并绑定点击事件-->
        <Button Content="Show!!!" Width="120" Height="80" Click="ButtonClick" />    
    </Grid>
</Window>

// MainWindow.xaml.cs

using System.ComponentModel;
using System.Globalization;
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 WpfApp1
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
		
		// 按钮的点击事件
        private void ButtonClick(object sender, RoutedEventArgs e)
        {
        	// 通过FindResource方法查找资源,并强制转换成 Human类型
            Human h = this.FindResource("human") as Human;
            if (h != null) {
                MessageBox.Show(h.Name);
            }
        }
    }

    public class Human
    {
    	// 声明两个属性
        public String Name { get; set; }
        public Human Child { get; set; }
    }

}
  • 该实例进阶: 如果新增Child属性,值为字符串,如何让程序把该值自动识别为Name值呢,代码逻辑如下
<Window x:Class="WpfApp1.MainWindow"
      ......>

    <Window.Resources>
    	<!-- 新增Child属性的字符串赋值 -->
        <local:Human x:Key="human" Name="Tim" Child="Little Tim" />
    </Window.Resources>
    <Grid>
       ......

    </Grid>
</Window>

using System.ComponentModel;
using System.Globalization;
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 WpfApp1
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void ButtonClick(object sender, RoutedEventArgs e)
        {
            Human h = this.FindResource("human") as Human;
            if (h != null) {
                // MessageBox.Show(h.Name);
                MessageBox.Show(h.Child.Name);
            }
        }
    }
	
	// "特性"
    [TypeConverterAttribute(typeof(NameToHumanTypeConverter))]
    public class Human
    {
        public String Name { get; set; }
        public Human Child { get; set; }
    }
	
	// 类型转换器实现
	// TypeConverter作用: 实现XAML字符串到复杂类型的自动转换
    public class NameToHumanTypeConverter : TypeConverter
    {
        public override object? ConvertFrom(ITypeDescriptorContext? context, CultureInfo? culture, object value)
        {
            string name = value.ToString(); // 获取XAML中的字符串值
            Human child = new Human(); 
            child.Name = name; // 赋值
            return child;
        }
    }

}
  • WPF实例: 绘制一个带红色矩形按钮的窗口
<Window x:Class="WpfApp2.MainWindow"
       ......>
    <Grid>
    	// <!--定义按钮-->
        <Button Width="120" Height="60" >
        	<!--定义按钮的内容-->
            <Button.Content>
                <Rectangle Width="80" Height="20" Stroke="Black" Fill="Red" />
            </Button.Content>
        </Button>

    </Grid>
</Window>

  • 绘制渐变色矩形实例,可以看出,代码很多
<Grid>
    <Rectangle Width="200" Height="160" Stroke="Black">
        <Rectangle.Fill>
            <LinearGradientBrush>
                <LinearGradientBrush.StartPoint>
                    <Point X="0" Y="0" />
                </LinearGradientBrush.StartPoint>
                <LinearGradientBrush.EndPoint>
                    <Point X="1" Y="1" />
                </LinearGradientBrush.EndPoint>
                <LinearGradientBrush.GradientStops>
                    <GradientStopCollection>
                        <GradientStop Offset="0.2" Color="LightBlue" />
                        <GradientStop Offset="0.7" Color="DarkBlue" />
                        <GradientStop Offset="1.0" Color="Blue" />
                    </GradientStopCollection>
                </LinearGradientBrush.GradientStops>
            </LinearGradientBrush>
        </Rectangle.Fill>
    </Rectangle>

</Grid>
  • 优化实例如下
<Grid>
    <Rectangle Width="200" Height="160" Stroke="Black">
        <Rectangle.Fill>
            <LinearGradientBrush>
                <LinearGradientBrush.GradientStops>
                    <GradientStop Offset="0.2" Color="LightBlue" />
                    <GradientStop Offset="0.7" Color="DarkBlue" />
                    <GradientStop Offset="1.0" Color="Blue" />
                </LinearGradientBrush.GradientStops>
            </LinearGradientBrush>
        </Rectangle.Fill>
    </Rectangle>
</Grid>
  • XAML中为对象属性赋值
- Attribute=Value
- 属性标签
- 标签拓展
  • 标签拓展实例
<Grid Margin="4">
    <Grid.RowDefinitions>
        <RowDefinition Height="24" /> <!-- 行0:高24px -->
        <RowDefinition Height="4" /> <!-- 行1:间距4px -->
        <RowDefinition Height="24" /> <!-- 行2:高24px -->
    </Grid.RowDefinitions>

    <!--文本框-->
                                <!--标签拓展-->
    <TextBox x:Name="tb" Text="{Binding ElementName=sld,Path=Value}" />
    <!--滑块-->
    <Slider x:Name="sld" Grid.Row="2" Value="50" Maximum="100" Minimum="0" />

</Grid>

事件模型

  • 关键对象解析
- 事件拥有者
- 事件
- 事件响应者
- 事件处理器
- 事件订阅(桥梁)
  • 图片
  • 点击事件实例
......
<Grid>
    <Button Content="Click Me" Height="100" Width="200" Click="Button_Click" />
</Grid>
......
namespace WpfApp3
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
		
		<!--点击事件相应-->
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("Hello");
        }
    }
}
  • 上面这个实例可以修改一下,变成下面这个样子
<Grid>
    <!--Click="Button_Click"-->
    <Button x:Name="button1" Content="Click Me" Height="100" Width="200"  />
</Grid>
......
namespace WpfApp3
{
 
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            // 利用委托,然后两次Tab键自动生成
            this.button1.Click += Button1_Click;
            // 这句也可以
            // this.button1.Click += new RoutedEventHandler(Button1_Click);
        }

        private void Button1_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("Hello");
        }

    }
}
  • 现在WPF的编程流行趋势,也可以像Vue一样,组件化编程,把一个个功能模块化,组件化,最终实现功能集
  • 实例如下,先新建一个WPF项目,然后再新建一个用户控件项目
<UserControl x:Class="WpfControlLibrary1.SalaryCalculator"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="240" Height="160" Background="LightBlue">
    <Canvas>
        <Label Content="基本工资" Height="38" Canvas.Left="10" Canvas.Top="10" Width="85" Name="label1" />
        <Label Content="岗位工资" Height="38" Canvas.Left="10" Canvas.Top="50" Width="85" Name="label2" />
        <Label Content="实际工资" Height="38" Canvas.Left="10" Canvas.Top="90" Width="85" Name="label3" />
        <TextBox Height="19" Canvas.Left="95" TextWrapping="Wrap" Text="TextBox" Canvas.Top="12" Width="121" Name="TextBox1" HorizontalAlignment="Center" VerticalAlignment="Top"/>
        <TextBox Height="19" Canvas.Left="95" TextWrapping="Wrap" Text="TextBox" Canvas.Top="53" Width="121" Name="TextBox2" HorizontalAlignment="Center" VerticalAlignment="Top"/>
        <TextBox Height="19" Canvas.Left="95" TextWrapping="Wrap" Text="TextBox" Canvas.Top="90" Width="121" Name="TextBox3" HorizontalAlignment="Center" VerticalAlignment="Top"/>
        <Button Content="计算" Height="22" Canvas.Left="95" Canvas.Top="128" Width="121" Name="Button1" Click="Button1_Click" />

    </Canvas>
</UserControl>


namespace WpfControlLibrary1
{

    public partial class SalaryCalculator : UserControl
    {
        public SalaryCalculator()
        {
            InitializeComponent();
        }
  
		// 响应点击事件
        private void Button1_Click(object sender, RoutedEventArgs e)
        {
            this.TextBox3.Text = this.TextBox2.Text + this.TextBox1.Text;
        }
    }
}

  • 主项目程序中先添加引用,引用该类库,然后调用组件
<Window x:Class="WpfApp4.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:WpfApp4"
        mc:Ignorable="d"
        <!--映射为controls-->
        xmlns:controls="clr-namespace:WpfControlLibrary1;assembly=WpfControlLibrary1"
        Title="MainWindow" Height="450" Width="800">
    <Grid>

        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>

        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
		
		<!--调用组件-->
        <controls:SalaryCalculator Grid.Column="0" Grid.Row="0" />
        <controls:SalaryCalculator Grid.Column="1" Grid.Row="0" />
        <controls:SalaryCalculator Grid.Column="0" Grid.Row="1" />
        <controls:SalaryCalculator Grid.Column="1" Grid.Row="1" />

    </Grid>
</Window>

posted @ 2025-05-13 16:54  清安宁  阅读(41)  评论(0)    收藏  举报