「詳しくて簡単な WPF」学習メモ

関連リソース

高解像度ビデオチュートリアル「シンプルな WPF 入門」シリーズ | 講師: Liu Tiemeng

wpf pdf 版の完全版をダウンロードします。簡単に言うと、
劉鉄蒙氏の B 駅番号です。ただし、最近のビデオ素材のみ
ここに画像の説明を挿入

序文

WPF は 2007 年に開発され、2010 年に正式にリリースされましたが、非常に高度な技術フレームワークです。MVVM 内部、ビジネス コード、インターフェイス コードは完全に分離されており、低結合と高凝集性の考え方は、その後のフロントエンド開発に常に影響を与えてきました。たとえば、Vue は MVVM から継承されます。

国内の就職市場における WPF の状況は決して理想的ではありませんが、その理由として、デスクトップ ソフトウェアが衰退し、機能が PC 側から WEB 側に徐々に移行していることが挙げられます。Web ページで解決できるのに、なぜクライアントが必要なのでしょうか? WPF技術の普及促進も課題だ。従来のインターネットの台頭により、Java は非常に高いレベルに引き上げられ、多くの車輪があり、特にエコロジーが優れており、Java を学ぶ人がたくさんいます。

したがって、WPF を学習したからといって、良い仕事が見つかるとは思わないでください。.NET エンジニアは依然として、フロントエンドとバックエンドの両方でフルスタックに切り替える必要があります。私は現在、最も単純なフルスタック テクノロジ スタックは Vue+uniapp+WPF+webApi+.NET core だと考えています。データベース: SQL サーバー sqlite Mysql。実際には、Unity 2d + Unity 3d + C4D を学ぶのが最善です。これは完全なフルスタックです。基本的には、解決できる単純な小さなプロジェクトです。

今年の私のテンプレートは、WPF+Unity 2d+C4D モデリングを学ぶことです。私の学習ロジックは常に低位から高位へ、つまり、最初にツールの使い方を学び、次に高度なことを掘り下げるというものでした。この部分を学んだ後、来年は Linux と Python を学び始める予定です。

C#とJAVAは競合しているので、Javaを学ぶ気力は当分ありません。必要なときにそれについて話します

少し話が逸れましたが、話を戻しますわかりやすいWPF、Liu Tiemeng先生は依然として非常に激しく、説明は非常に優れています。他のクラスとは異なり、最初にコントロールのプロパティについて数時間説明します。それは原理から直接始まり、最下層からアプリケーションまで、非常に明確です。

WPFの勉強メモ

ビデオデータアドレス

高解像度ビデオチュートリアル「シンプルな WPF 入門」シリーズ | 講師: Liu Tiemeng

環境構成

  • .NETコア6.0
  • WPF

ここに画像の説明を挿入

WPF の基本: WPF プログラムの開始方法

私たちが作成した単純な WPF プログラム。
ここに画像の説明を挿入

xmalファイルとcsファイルはどのように接続されていますか

ページとサービスを分離するために、WPF ではページのみを xmal に記述し、サービスを cs ファイルに記述するように強制されます。この強制的な分離は結合を減らすためのものです。JQuery プロジェクトを維持しようとした学生がいるなら、ビジネスとページが分離されていないことがどれほど苦痛であるかを理解するでしょう。関数にはページ ロジックとビジネス ロジックが含まれているため、後の段階で変更を行う場合は関数全体の動作を十分に理解する必要があり、変数を任意に削除すると直接エラーが報告されます。

App.xmal と App.xaml.cs を例に挙げてみましょう
ここに画像の説明を挿入
ここに画像の説明を挿入

ここに画像の説明を挿入

スプラッシュページの決め方

ここに画像の説明を挿入

xmal ファイルはどのように他のファイルを参照するのか

ここに画像の説明を挿入

どのように引用するか

ここに画像の説明を挿入
ここに画像の説明を挿入

WPF が要素を作成し、要素を変更する方法

WPF は、ページとビジネスの高度なセグメント化を実行し、コンパイルを通じて対応するページとファイルをマップします。すべての要素の作成と単純な対話イベントは xmal で発生します。

WPF 要素の作成と単純な属性の割り当て

単純なボタンを例に挙げます

レイアウト要素にコントロールを作成します。

<Grid>
    <Button  Content="Show Msg!"//显示的文字
             Click="Button_Click"//点击事件
             Width="100"//宽度
             Height="30" />//高度
</Grid>

<> で囲まれたものはラベルであり、<> の後に属性が続きます。上の例では、Button がラベルであり、Grid もラベルです。コンテンツ、クリック、幅、高さはすべて属性です。
効果を達成する

ここに画像の説明を挿入

WPFツリーインターフェイス

WPF の xmal は html に非常に似ており、どちらもマークアップ言語です。

ここに画像の説明を挿入
ここに画像の説明を挿入
ここに画像の説明を挿入
このツリー階層が WPF の階層です。

もっと詳しく知りたい場合は、私の以前の記事を読んでください。
WPF がページ要素をリアルタイムで表示する方法 リアルタイム ビジュアル ツリーの使用方法

Xmal 属性の割り当て

Xmal には属性を割り当てる方法が 3 つあります。

  • インラインラベル: デフォルトの割り当て方法
  • プロパティ ラベル: 文字列入力変換データ型
  • 拡張タブ

複数の属性を割り当てる理由

最も単純な Button ボタンを見てみましょう

<Grid>
    <Button  Content="Show Msg!"//字符串标签
             Click="Button_Click"
             Width="100"//属性标签
             Height="30" />
</Grid>

割り当てた値がすべて文字列であることがわかります。Content と同様、属性値は文字列である必要がありますが、Width と Height の属性値は数値である必要がありますが、入力する値も文字列です。明確にするために、コピーした文字列を変換できます。

属性変換

属性変換の目的は、タグ属性を通じて複雑な情報を生成することです。たとえば、高さ = "100" とします。高さには文字列が割り当てられますが、これは数値に変換する必要があります。

新しい Person クラスを作成します

メインウィンドウ.cs

namespace WpfLearnTest
{
    
    
    public partial class MainWindow : Window
    {
    
    
        public MainWindow()
        {
    
    
            InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e)//按钮事件
        {
    
    
        	///找到资源字典中名字为person的类
            Person _model = (Person)this.FindResource("person");
            MessageBox.Show(_model.Name);
        }
    }

    public class Person
    {
    
    
        public string Name {
    
     get; set; }

        public Person Chil {
    
     get; set; }

    }
}

MainWindow.xmal

<Window x:Class="WpfLearnTest.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:WpfLearnTest"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
     
    
    <Window.Resources>
        <local:Person x:Key="person" Name="小王" />//声明Person类
    </Window.Resources>
    <Grid>
        <Button  Content="Show Msg!"
                 Click="Button_Click"//添加点击按钮
                 Width="100"
                 Height="30" />
    </Grid>
</Window>

結果を達成する

ここに画像の説明を挿入
これが機能する理由は、Person クラスの Name が文字列であるためですが、文字列でない場合はどうなるでしょうか。
ここに画像の説明を挿入

ここに画像の説明を挿入

Child がエラーを報告していることがわかります。文字列を Person クラスに直接転送することはできません。

解決
	///引入属性转换
    [TypeConverterAttribute(typeof(NameToPersonTypeConverter))]
    public class Person
    {
    
    
        public string Name {
    
     get; set; }

        public Person Child {
    
     get; set; }

    }
    /// <summary>
    /// 添加属性转换
    /// </summary>
    public class NameToPersonTypeConverter : TypeConverter
    {
    
    
        public override object? ConvertFrom(ITypeDescriptorContext? context, CultureInfo? culture, object value)
        {
    
    
            string name = value.ToString();
            Person child = new Person();

            child.Name = name;
            return child;
        }
    }

効果:

ここに画像の説明を挿入
ここに画像の説明を挿入
操作結果は成功です!

ここに画像の説明を挿入

プロパティラベル

解決する必要がある問題。

ここに画像の説明を挿入

Web ページでは、Html+CSS でどのように実装されますか?

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>一个简单的网页</title>
	</head>
	<body>
        <div>
            <button style="width: 100px;height: 30px;">
                <div style="height: 10px;min-width: 10px;border: 1px solid red;display: inline-block;"></div>
            </button>
        </div>

	</body>
</html>

ここに画像の説明を挿入
ネストはxmalでも使用できます

<Window x:Class="WpfLearnTest.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:WpfLearnTest"
        mc:Ignorable="d"
        Title="MainWindow"
        Height="450"
        Width="800">


    <Grid>
        <Button 
                Width="100"
                Height="30">
            <Rectangle Width="20"
                       Height="20"
                       Stroke="DarkGreen"
                       Fill="LawnGreen" />

        </Button>
    </Grid>
</Window>

ここに画像の説明を挿入
しかし、xmal は使用をサポートしています。プロパティラベル埋める

        <Button Click="Button_Click"
                Width="100"
                Height="30">
            <Button.Content>//属性标签,对应button的content值
                <Rectangle Width="20"
                           Height="20"
                           Stroke="DarkGreen"
                           Fill="LawnGreen" />
            </Button.Content>
        </Button>

得られる効果は同じです
ここに画像の説明を挿入

では、属性タグをネストすると何になるのでしょうか?

結論から言えば、この場合には違いはありません。

リアルタイム ビジュアル ツリーでは違いはありません
ここに画像の説明を挿入

属性タグの長所と短所

今、私たちにはニーズがあります
ここに画像の説明を挿入

        <Rectangle Width="200"
                   Height="160"
                   Stroke="Blue"
                   Fill="LightBlue" />

html+css でどのように解決するかを見てみましょう
Web ページは html+css+JS で区切られています。HTML で要素を宣言し、CSS でスタイルを変更するだけにしてください。原則として、JS は使用中に HTML 要素を追加または削除しません (DOM 操作は実装できますが、結合が増加し、クソ山コードが簡単に形成されます) が、CSS 表示: なしを介して行われます。ページスタイルを表示するかどうかを指定します。

声明页面元素
修改Html样式
动态html对应的CSS
实现业务逻辑
原则上不能直接操控Html
的元素生成
原则上不能修改CSS的样式内容
用户页面
Html
CSS
JS
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>一个简单的网页</title>
</head>
<body>
    <div id="box">
    </div>
</body>
</html>
<style type="text/css">
    #box {
      
      
        height: 200px;
        background-color: red;
        background-image: linear-gradient(to bottom right, red, blue);
    }
</style>

効果を達成する
ここに画像の説明を挿入

属性タグの欠点

上記の効果を達成するために WPF を記述する方法を見てみましょう。

<Rectangle Width="200"
                   Height="160"
                   Stroke="Blue">
            <Rectangle.Fill>
                <LinearGradientBrush>
                    <LinearGradientBrush.StartPoint>
                        <Point  X="0"
                                Y="0" />
                    </LinearGradientBrush.StartPoint>
                    <LinearGradientBrush.EndPoint>
                        <Point X="1"
                               Y="1" />
                    </LinearGradientBrush.EndPoint>
                    <LinearGradientBrush.GradientStops>
                        <GradientStop Offset="0.2"
                                      Color="LightBlue" />
                        <GradientStop Offset="0.7"
                                      Color="DarkBlue" />
                        <GradientStop Offset="1.0"
                                      Color="LightBlue" />
                    </LinearGradientBrush.GradientStops>
                </LinearGradientBrush>
            </Rectangle.Fill>
        </Rectangle>

ここに画像の説明を挿入

単純なグラデーション効果であることがわかりますので、記述するのは非常に面倒です

もちろん、インラインタグを使用して最適化することもできます

<Rectangle Width="200"
                   Height="160"
                   Stroke="Blue">
            <Rectangle.Fill>
                <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">//使用行内标签来对代码进行优化
                    <LinearGradientBrush.GradientStops>
                        <GradientStop Offset="0.2"
                                      Color="LightBlue" />
                        <GradientStop Offset="0.7"
                                      Color="DarkBlue" />
                        <GradientStop Offset="1.0"
                                      Color="LightBlue" />
                    </LinearGradientBrush.GradientStops>
                </LinearGradientBrush>
            </Rectangle.Fill>
        </Rectangle>

リソースディクショナリを使用して最適化できます

 <Window.Resources>
        <Style x:Key="MyButton"
               TargetType="Button">
            <Style.Setters>
                <Setter Property="Content"
                        Value="" />
            </Style.Setters>
        </Style>
        <Style x:Key="MyRectFill" TargetType="Rectangle">
            <Style.Setters>
                <Setter Property="Fill" >
                    <Setter.Value>
                        <LinearGradientBrush StartPoint="0,0"
                                             EndPoint="1,1">
                            <GradientStop Offset="0.2"
                                          Color="LightBlue" />
                            <GradientStop Offset="0.7"
                                          Color="DarkBlue" />
                            <GradientStop Offset="1.0"
                                          Color="LightBlue" />
                        </LinearGradientBrush>
                    </Setter.Value>
                </Setter>
            </Style.Setters>
        </Style>
    </Window.Resources>
    <Grid>
        <Rectangle Width="200"
                   Height="160"
                   Stroke="Blue" Style="{ 
        StaticResource MyRectFill}" >
        </Rectangle>
    </Grid>

ページ要素は確実に簡略化されていますが、WPF の動作上、Window.Resources はページ要素の前にしか配置できません。また、C# や Xmal は厳密に定義された言語であるため、記述する際に要素の内容を宣言する必要があります。

CSS では 5 行で解決できることが、Xmal では 10 行で解決できます。

拡張タブ

先ほど書いたコードでは

        <Rectangle Width="200"
                   Height="160"
                   Stroke="Blue" Style="{ 
        StaticResource MyRectFill}" >//这个就是扩展标签
        </Rectangle>

拡張タグは、{} の形式を使用して属性値を含めます。このとき入力するのは文字列ではなく属性オブジェクトです。生徒が学習した場合ヴューこれは次のようなものであることがわかります。ヴュー差分式 { {値}}。

タグ拡張機能は通常、属性バインディングで動作します。属性バインディングの使用方法については後ほど説明します。これが WPF の焦点です。

WPF プロパティのバインド

ページ要素の相互の割り当て

先ほど、WPF におけるコンテンツの関係は次のとおりであると述べました。

负责所有的页面元素
样式和简单的用户交互
C#
复杂的交互逻辑
业务逻辑
Xmal
负责Style管理和资源管理
windows.Resource
Style
负责样式管理,触发器管理
xmal元素
负责声明元素
用户页面
数据交互和触发事件回调

xmal では要素を通信できますが、Web 側では通信できません。Web は JS イベント トリガーを通じてデータを変更する必要があります。これはイベント駆動型です。イベント駆動型では、すべてのページ操作はイベントによってトリガーされ、2 つのページ要素間の通信には中間イベントが必要であると考えられます。

修改对应元素值
页面A数据修改
触发JS函数
B元素修改

Xmal では、これはデータ駆動型であるか、匿名イベントと見なすことができます。つまり、イベントを宣言する必要はなく、値を直接与えるだけです。

A被修改属性
xmal元素A
xmal元素B联动

xmalコード

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="24" />
            <RowDefinition Height="4" />
            <RowDefinition Height="24" />
        </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>

ここに画像の説明を挿入

WPF データ バインディングについては、Prism フレームワークで後ほど詳しく説明します。

WPFのコンポーネント化

コンポーネント化とは、再利用可能なインターフェイスをコンポーネントにカプセル化することを意味します。WPFには4つのクラスがあります

ここに画像の説明を挿入

  • 窓:窓。Windows をネストすることはできません
  • ページ: めったに使用されず、何をするのかわかりませんが、Web ページのようです。
  • ユーザー コントロール: ウィンドウの上部に設定します。コンポーネントを抽象化するため
  • リソース ディクショナリ: スタイルやコントロールなどの WPF リソースを管理するために使用されます。

新しい WPF リソース クラスを作成します

ここに画像の説明を挿入
ここに画像の説明を挿入
新しいプロジェクト

次に、次のコードを追加します

UserControl1.xmal

<UserControl x:Class="ControlLibrary.UserControl1"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:local="clr-namespace:ControlLibrary"
             mc:Ignorable="d"
             d:DesignHeight="160"
             d:DesignWidth="240"
             Background="LightBlue">
    <Canvas>
        <TextBox Canvas.Left="110"
                 TextWrapping="Wrap"
                 x:Name="textBox1"
                 Canvas.Top="10"
                 Width="120"
                 HorizontalAlignment="Left"
                 VerticalAlignment="Center"/>
        <TextBox Canvas.Left="110"
                 TextWrapping="Wrap"
                 x:Name="textBox3"
                 Canvas.Top="105"
                 Width="120"
                 HorizontalAlignment="Left"
                 VerticalAlignment="Top" />
        <TextBox Canvas.Left="110"
                 TextWrapping="Wrap"
                 x:Name="textBox2"
                 Canvas.Top="63"
                 Width="120"
                 HorizontalAlignment="Left"
                 VerticalAlignment="Center" />
        <TextBlock TextWrapping="Wrap"
                   Canvas.Top="10"
                   Canvas.Left="10"><Run Language="zh-cn"
                                         Text="num1" /></TextBlock>
        <TextBlock TextWrapping="Wrap"
                   Canvas.Top="63"
                   Canvas.Left="10"
                   HorizontalAlignment="Center"
                   VerticalAlignment="Top"><Run Text="num" /><Run Language="zh-cn"
                                                                  Text="2" /></TextBlock>
        <TextBlock TextWrapping="Wrap"
                   Canvas.Top="107"
                   Canvas.Left="10"
                   HorizontalAlignment="Center"
                   VerticalAlignment="Top"><Run Language="zh-cn"
                                                Text="总计" /></TextBlock>
        <Button Content="计算"
                Canvas.Left="126"
                Canvas.Top="136"
                HorizontalAlignment="Left"
                VerticalAlignment="Center"
                Width="88"
                Click="Button_Click" />
    </Canvas>
</UserControl>

UserControl.xmal.cs

using System;
......

namespace ControlLibrary
{
    
    
    /// <summary>
    /// UserControl1.xaml 的交互逻辑
    /// </summary>
    public partial class UserControl1 : UserControl
    {
    
    
        public UserControl1()
        {
    
    
            InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
    
    
                        this.textBox3.Text = ( int.Parse(this.textBox1.Text) + int.Parse(this.textBox2.Text) ).ToString();

        }
    }
}

ここに画像の説明を挿入

そしてそれに参照を追加します

ここに画像の説明を挿入
すべてのプロジェクトを再生成する
ここに画像の説明を挿入

main関数で参照される

<Window x:Class="WpfLearnTest.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:WpfLearnTest"
        xmlns:sys="clr-namespace:System.Security.Claims;assembly=mscorlib"
        xmlns:controls="clr-namespace:ControlLibrary;assembly=ControlLibrary"
        mc:Ignorable="d"
        Title="MainWindow"
        Height="450"
        Width="800">

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <controls:UserControl1 Grid.Row="0"
                               Grid.Column="0" />
        <controls:UserControl1 Grid.Row="1"
                               Grid.Column="1" />
        <controls:UserControl1 Grid.Row="1"
                               Grid.Column="0" />

        <controls:UserControl1 Grid.Row="0"
                               Grid.Column="1" />
    </Grid>
</Window>

ここに画像の説明を挿入

使用結果
ここに画像の説明を挿入

直接インポートして、ユーザー コントロールのコードを実行できます (合計結果は num1+num2 になります)。

おすすめ

転載: blog.csdn.net/qq_44695769/article/details/131348652