WPF入门

前言

减少自己的技术盲区。

1.WPF介绍

WPF(Windows Presentation Foundation)是由微软推出的一种用户界面框架,最初作为.NET Framework 3.0的一部分发布,但后来也被应用于更新的Windows操作系统中。WPF提供了一个统一的编程模型、语言和框架,这有助于将界面设计人员和开发者的工作相分离。它的目标是提供一个现代化的图形系统和用户体验,能够在多种设备和屏幕尺寸上运行,包括桌面电脑、平板电脑和移动设备。

WPF的核心是一个基于矢量的呈现引擎,该引擎利用现代图形硬件,并提供了一套完善的应用程序开发功能,如XAML(Extensible Application Markup Language)、控件、数据绑定、动画、布局、图形、文本和版式等。此外,WPF还包含了对.NET API的支持,允许开发者编写整合这些API的其他元素的应用程序。

WPF项目介绍

  • XAML:可扩展应用程序标记语言(Extensible Application Markup Language),它是微软公司为构建应用程序用户界面而创建的一种新的描述性语言。XAML提供了一种便于扩展和定位的语法来定义和程序逻辑分离的用户界面,而这种实现方式和ASP.NET中的代码后置模型非常类似。XAML是一种解析性的语言,尽管它也可以被编译。它的优点是简化编程式上的用户创建过程,应用时要添加代码和配置等。

  • 窗口、用户控件(如:环形图)、资源字典、页面(很少)

image-20240318211724563

创建窗体(WPF)

StartupUri:配置启动项

image-20240318212420166

创建页

image-20240318212651176

2.Grid

2.1Window

官网地址:https://learn.microsoft.com/zh-cn/dotnet/desktop/wpf/advanced/xaml-namespaces-and-namespace-mapping-for-wpf-xaml?view=netframeworkdesktop-4.8&viewFallbackFrom=netdesktop-8.0

默认映射整个 WPF 客户端/框架 XAML 命名空间:

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

第二个声明映射单独的 XAML 命名空间,(通常)将其映射到 x: 前缀。

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

官网地址:https://learn.microsoft.com/zh-cn/windows/uwp/xaml-platform/xaml-namespaces-and-namespace-mapping

“d:”XAML 命名空间旨在提供设计器支持,尤其是 Microsoft Visual Studio 的 XAML 设计界面中的设计器支持。 “d:”XAML 命名空间支持 XAML 元素上的设计器或设计时特性。

“mc:”表示并支持读取 XAML 的标记兼容性模式。 通常,“d:”前缀与特性 mc:Ignorable 相关联。 此技术使运行时 XAML 分析器忽略“d:”中的设计特性。

mc:Ignorable:代表只在设计器有效,运行时忽略。

image-20240318221506876

2.2Grid

创建3行3列

ShowGridLines="True":显示边框。

Grid.RowDefinitions:设置行数。

Grid.ColumnDefinitions:设置列数。

RowDefinition:设置行,只能设置高度。

ColumnDefinition:设置列,只能设置宽度。

Grid.Row="1":设置第几行,从0开始。

Grid.Column="1":设置第几列,从0开始。

image-20240318223322787

2.3UniformGrid

UniformGrid:自动创建行列。每个单元格大小相同。一般用于动态绑定数据。

UniformGrid Columns:设置列数。

image-20240318224059497

2.4StackPanel

StackPanel:紧凑堆一起(可设置横着堆或竖着堆),一个紧挨一个,放不下就截取。

Orientation :

  • Horizontal:垂直排列。
  • Vertical:水平排列。

image-20240318224404128

2.5Border

Border(边框)是一个装饰的控件,此控件绘制一个边框、一个背景。Border 中只能有一个子控件(Child),若要显示多个子元素,需要在父Border元素中放置一个附加Panel元素,然后可以将子元素放置在该 Panel 元素中。

Border Background:背景色。

Border BorderBrush:边框颜色。

Border BorderThickness:边框长度。0,0,5,0(顺时针:左上右下) 5,0(左右,上下)。

image-20240318224948899

3.Style

Grid均分4行,每行建立一个按钮,每个按钮添加样式,背景色不同。

image-20240319212448995

Window.Resources定义Button样式,类似把Button的样式都封装起来。

image-20240319212811845

资源的名称用Key,控件的名称用Name。

Key:给封装的样式命名。

StaticResource:通过名称指定样式。

image-20240319213159462

BasedOn:继承样式。可以把相同过的样式封装起来,不同的样式单独再调用公共样式。

image-20240319213819968

4.全局样式和资源字典

把样式添加到资源字典。

image-20240319214506235

在App.xaml中把样式添加到全局。

image-20240319214557525

5.自定义样式模版和触发器

添加button模版。

image-20240319215406378

通过TemplateBinding绑定Button属性。

image-20240319215656931

x:Name:给Border和TextBlock命名。触发器时需要指定控件名称。

IsMouseOver:鼠标移动到控件上时触发。改变borderCus的Background和txtCus的Text。

IsPressed:鼠标离开控件时触发。。改变borderCus的Background。

image-20240319220628559

6.登录界面设计

使用Grid排版布局。

HorizontalAlignment:水平位置。

VerticalAlignment:垂直位置。

Grid.ColumnSpan:合并列。

<Window x:Class="Peng.OAManager.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:Peng.OAManager"
        mc:Ignorable="d"
        Title="在线办公管理系统" Height="450" Width="800">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="40"></RowDefinition>
            <RowDefinition ></RowDefinition>
        </Grid.RowDefinitions>

        <!--第一行-->
        <Border Background="#0078d4">
            <TextBlock Text="在线办公管理系统"  FontWeight="Light" FontSize="20" VerticalAlignment="Center" HorizontalAlignment="Center"></TextBlock>
        </Border>

        <!--第二行-->
        <Grid Grid.Row="1">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="180"></ColumnDefinition>
                <ColumnDefinition></ColumnDefinition>
            </Grid.ColumnDefinitions>
            <!--第一列-->
            <Border>
                <Image Source="Img/Login.png" Width="90" Height="90"></Image>
            </Border>
            <!--第二列-->
            <Border Grid.Column="1" Background="LightCyan">
                <Grid HorizontalAlignment="Center" VerticalAlignment="Center" Width="200" Height="200">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="30"></RowDefinition>
                        <RowDefinition Height="30"></RowDefinition>
                        <RowDefinition Height="auto"></RowDefinition>
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="80"></ColumnDefinition>
                        <ColumnDefinition Width="120"></ColumnDefinition>
                    </Grid.ColumnDefinitions>

                    <!--账号-->
                    <TextBlock Text="账号" VerticalAlignment="Center" HorizontalAlignment="Center"></TextBlock>
                    <TextBox Grid.Column="1" ></TextBox>

                    <!--密码-->
                    <TextBlock Text="密码" Grid.Row="1"  VerticalAlignment="Center" HorizontalAlignment="Center"></TextBlock>
                    <TextBox Grid.Row="1" Grid.Column="1" ></TextBox>

                    <Button Content="登录" Grid.Row="2" Grid.ColumnSpan="2" FontSize="20" Background="LightBlue" Margin="0 10 0 0"></Button>
                </Grid>
            </Border>
        </Grid>
    </Grid>
</Window>

7.MVVM登录实现

AccountModel

image-20240319225149026

实现INotifyPropertyChanged

image-20240319225218003

设置数据上下文 (视图模型)

image-20240319225257131

双向绑定

image-20240319225359675

8.委托

子窗体声明一个事件(Func:有参有返回值委托),传入int和string参数。

image-20240319231250763

父窗体按钮点击订阅事件。

将doWork传给子窗体,由子窗体执行,子窗体传值。

image-20240319231421009

9.附加属性

新建PasswordBoxExtend,俩下Tab

image-20240320220900768

image-20240320220934364

实现PasswordBoxExtend:

当CusPassWord的值发生改变,给Password属性赋值。

PasswordBoxExtend.IsBind判断俩个值有没有改变。

当Password的值发生改变,给CusPassWord属性赋值。

public class PasswordBoxExtend
{
    /// <summary>
    /// 获取属性
    /// 附加属性(特殊的依赖属性)
    /// </summary>
    /// <param name="obj"></param>
    /// <returns></returns>
    public static string GetCusPassWord(DependencyObject obj)
    {
        return (string)obj.GetValue(CusPassWordProperty);
    }

    /// <summary>
    /// 设置属性
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="value"></param>
    public static void SetCusPassWord(DependencyObject obj, string value)
    {
        obj.SetValue(CusPassWordProperty, value);
    }

    // Using a DependencyProperty as the backing store for MyProperty.  This enables animation, styling, binding, etc...
    /// <summary>
    /// CusPassWord->PassWord 当CusPassWord的值发生改变,给Password属性赋值
    /// </summary>
    public static readonly DependencyProperty CusPassWordProperty =
        DependencyProperty.RegisterAttached("CusPassWord", typeof(string), typeof(PasswordBoxExtend), new PropertyMetadata("", OnCusPassWordChanged));//Alt+Enter 自动生成OnCusPassWordChanged方法

    /// <summary>
    /// 当CusPassWord的值发生改变,给Password属性赋值
    /// </summary>
    /// <param name="d"></param>
    /// <param name="e"></param>
    private static void OnCusPassWordChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        PasswordBox pwdBox = d as PasswordBox;
        if (pwdBox != null)
        {
            pwdBox.Password = (string)e.NewValue;//当CusPassWord的值发生改变,给Password属性赋值

            //将光标移动最后
            SetSelection(pwdBox, pwdBox.Password.Length, 0);
        }
    }

    /// <summary>
    /// 设置光标位置
    /// </summary>
    /// <param name="passwordBox"></param>
    /// <param name="start">光标开始位置</param>
    /// <param name="length">选中长度</param>
    private static void SetSelection(PasswordBox passwordBox, int start, int length)
    {
        passwordBox.GetType()
                   .GetMethod("Select", BindingFlags.Instance | BindingFlags.NonPublic)
                   .Invoke(passwordBox, new object[] { start, length });
    }


    public static bool GetIsBind(DependencyObject obj)
    {
        return (bool)obj.GetValue(IsBindProperty);
    }

    public static void SetIsBind(DependencyObject obj, bool value)
    {
        obj.SetValue(IsBindProperty, value);
    }

    // Using a DependencyProperty as the backing store for IsBind.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty IsBindProperty =
        DependencyProperty.RegisterAttached("IsBind", typeof(bool), typeof(PasswordBoxExtend), new PropertyMetadata(false,OnBindChanged));

    private static void OnBindChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        PasswordBox pwdBox = d as PasswordBox;
        if (pwdBox != null)
        {
            //1、如何Passwrod属性变化了,则通知CusPassWord也要变
            //2、如果Passwrod属性没有变,则不用通知CusPassWord
            if ((bool)e.NewValue)//如果是新值  已经变了
            {
                pwdBox.PasswordChanged += OnPasswordChanged;
            }
            if ((bool)e.OldValue)//如果是旧值  没有变 
            {
                pwdBox.PasswordChanged -= OnPasswordChanged;
            }
        }
    }

    private static void OnPasswordChanged(object sender, RoutedEventArgs e)
    {
        PasswordBox pwdBox = sender as PasswordBox;
        if (pwdBox != null)
        {
            SetCusPassWord(pwdBox, pwdBox.Password);
        }
    }
}

添加命名空间。

PasswordBoxExtend.IsBind="True":判断值是否改变,默认是true。

cuspwdns:PasswordBoxExtend.CusPassWord:绑定PassWord。

Mode=TwoWay:双向绑定。

UpdateSourceTrigger=PropertyChanged:值改变时触发

image-20240320224302884

10.自定义控件

继承Button,自定义BtnRadius和OverBackground。

image-20240320234426940

自定义样式,传入CornerRadius和Background。

image-20240320234523824

在App添加样式资源。

image-20240320234621819

添加命名空间,然后加入自定义控件。

image-20240320234704985

创作不易,感谢支持。
wxzf

posted @   peng_boke  阅读(2873)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
点击右上角即可分享
微信分享提示