WPF【09】WPF基础入门 (三层架构与MVC架构)

9-2 【操作】WPF 基础入门
新建一项目
Create a new project - WPF Application (A project for creating a .NET Core WPF Application) - Next - .NET 5.0 (Current) - Create

项目创建完成,VS自动打开 GUI用户界面,格式是 .xaml文件,跟xml差不多,也属于xml文件的类别。
虽然xaml是WPF用户的底层标准,但是VS已帮我们全部封装好了,可以直接拖拽布局界面。

9-3 【理论】XAML页面剖析
MainWindow.xaml代码示例
        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:WpfApp"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
   
       

cs中代码
private void Button_Click(object sender, RoutedEventArgs e)
{
    MessageBox.Show("按钮被点击了!"); //这里加入断点
}

给上面点击事件,加入断点。启动调试,在“Autos”中,找到“Name”中 sender 对应的“Value”中,鼠标放到放大镜上,提示“WPF Tree Visualizer”,点击【放大镜】进入视觉树查看页面。
在这个窗口中,左边是视觉树,右边是当前视觉树(选中的)节点所有的属性。

从页面来说整个像是一棵树被倒过来一样。从树根出发,一层一层开枝散叶,树根 MainWindow ,而 MainWindow 连接的是视觉节点 Border(边框),继续连接后续的视觉节点等等。
不过,在视觉树中,也可以找到逻辑节点。比如 StackPanel、TextBlock、ListBox 等等。

从原理来说,逻辑树是视觉树的子集

WPF【09】WPF基础入门 (三层架构与MVC架构)_第1张图片

逻辑树是视觉树的子集示例图

9-6 【操作】Grid 网格系统

Grid网格是WPF中最基本的行列布局工具。
示例:3行3列的网格布局

   
       
       
       
   

   
       
       
       
   

   
   
   
   
    Hello World

Width值中:* 是权重操作,值还可以是 auto,或 数字(表示像素) 等

9-7 【操作】依赖属性与数据处理



在xaml中到处都是属性,像这边Button中的属性Height等,所有这些属性都依赖于 Button.Style 中所定义的 property,也就是说,这些UI上的属性 与 事件触发属性是绑定在一起的,从数据流动的角度来说,这就是数据绑定最基本的逻辑。属性依赖也可以让相关的UI控件知道,当前事件的处理逻辑

public class Button : ButtonBase {
    public static readonly DependencyProperty IsCancelProperty;
    public static readonly DependencyProperty IsDefaultedProperty;
    public static readonly DependencyProperty IsDefaultProperty;
    public Button();
    public bool IsCancel{ get; set; }
    public bool IsDefault { get; set; }
    public bool IsDefaulted { get; }
    ……
}

这里可以看到3个readonly的DependencyProperty,也就是属性依赖,分别用来判断默认属性、属性取消、以及是否回到默认属性。同时对应这三个依赖属性,还有3个基础属性,在程序正常运行时,这3个基础属性会与依赖属性互相连接,而这3组属性则可以控制UI控件中的动态变化。比如,样式数据的绑定、动画效果,甚至样式的继承。

而在这个 ButtonBase 中,继承于ContentControl,在它内部除了有可以处理事件的 RoutedEvent 以外,所有其他的都是依赖属性。
public abstract class ButtonBase : ContentControl, ICommandSource {
    public static readonly RoutedEvent ClickEvent;
    public static readonly DependencyProperty ClickModeProperty;
    public static readonly DependencyProperty CommandParameterProperty;
    public static readonly DependencyProperty CommandProperty;
    public static readonly DependencyProperty CommandTargetProperty;
    public static readonly DependencyProperty IsPressedProperty;
    ……
}
public class ContentControl : Control, IAddChild {
    ……
}

让我们更深入一点,进入ContentControl,再进入 Control,同样可以看到类似的属性依赖,可以看到刚刚使用过的 FontSizeProperty 字体大小、ForegroundProperty 前景,等各种各样其他的属性,对于WPF的UI控件来说,属性依赖是最基础的数据和最基础的事件传递机制。

public class Control : FrameworkElement {
    public static readonly DependencyProperty BackgroundProperty;
    public static readonly DependencyProperty TemplateProperty;
    public static readonly DependencyProperty TabIndexProperty;
    public static readonly RoutedEvent PreviewMouseDoubleClickEvent;
    public static readonly DependencyProperty PaddingProperty;
    public static readonly RoutedEvent MouseDoubleClickEvent;
    public static readonly DependencyProperty IsTabStopProperty;
    …………
    public static readonly DependencyProperty FontSizeProperty;
    …………
    public static readonly DependencyProperty ForegroundProperty;
}


9-8 【操作】Data Binding 数据绑定

1. 单向绑定 one way bining : Source -> Target
2. 双向绑定 two way bining : Source <-> Target
3. 指定方向单向绑定 oneWayToSource Target -> Source
4. 单次绑定 One Time -> 构造方法中单次执行


   
   

指定绑定的数据内容是什么?指定数据需要使用 Path 属性,这里的 Path 其实是 Slider 的数据,也就是 Value,最后指定绑定方式。
IsSnapToTickEnabled="True" 则显示的数字,拖动不会显示小数了。

有什么办法,不需要按下 Tab键,就进行数据绑定呢?
有,加上 UpdateSourceTrigger=PropertyChanged 

One Time绑定,就是一次性的绑定。
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        mySlider.Value = 35;
        myTextBox.Text = mySlider.Value.ToString();
    }
}

9-9 【操作】INotifyPropertyChanged 事件处理


   
   
   
   
   
   

cs中代码:
public partial class MainWindow : Window
{
    public Sum Sum { get; set; }

    public MainWindow()
    {
        InitializeComponent();
        Sum = new Sum() { Num1 = "1", Num2 = "2" };
        this.DataContext = Sum;
    }
}

新建一个Sum.cs类文件。Sum实现INotifyPropertyChanged接口(在 System.ComponentModel 命名空间下),让VS自动实现接口:public event PropertyChangedEventHandler PropertyChanged;
这样就多了一个方法 PropertyChangedEventHandler,它是一个典型的事件处理委托。
接着来添加事件的触发处理 OnPropertyChanged 方法,因为 TextBox的输入都是字符串,所以监听数据是 string property。

为了能够处理这三个TextBox的联动,还需要在 Num1和Num2 的Set中发送 OnPropertyChanged("Result"); 计算Result这个事件。


public class Sum : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string property)
    {
        if (PropertyChanged == null) //防御性编程
        {
            return;
        }
        PropertyChanged(this, new PropertyChangedEventArgs(property)); //事件处理机制
    }

    private string _num1;
    private string _num2;
    private string _result;

    public string Num1
    {
        get
        {
            return _num1;
        }
        set
        {
            int number;
            bool result = int.TryParse(value, out number);
            if(result)
            {
                _num1 = value;
                OnPropertyChanged("Num1");
                OnPropertyChanged("Result");
            }
        }
    }

    public string Num2
    {
        get
        {
            return _num2;
        }
        set
        {
            int number;
            bool result = int.TryParse(value, out number);
            if (result)
            {
                _num2 = value;
                OnPropertyChanged("Num2");
                OnPropertyChanged("Result");
            }
        }
    }

    public string Result
    {
        get
        {
            int result = int.Parse(_num1) + int.Parse(_num2);
            return result.ToString();
        }
        set
        {
            int result = int.Parse(_num1) + int.Parse(_num2);
            _result = result.ToString();
            OnPropertyChanged("Result");
        }
    }
}


 

你可能感兴趣的:(wpf)