【.NET深呼吸】用代碼寫WPF控制項模板

来源:https://www.cnblogs.com/tcjiaan/archive/2023/06/18/17487725.html
-Advertisement-
Play Games

這一次咱們來探究一下怎麼用純代碼寫 WPF 模板。模板有個共同基類 FrameworkTemplate,數據模板、控制項模板等是從此類派生的,因此,該類已定義了一些通用成員。 用代碼構建模板,重要的成員是 VisualTree 屬性,它的類型是 FrameworkElementFactory。可見,模 ...


這一次咱們來探究一下怎麼用純代碼寫 WPF 模板。模板有個共同基類 FrameworkTemplate,數據模板、控制項模板等是從此類派生的,因此,該類已定義了一些通用成員。

用代碼構建模板,重要的成員是 VisualTree 屬性,它的類型是 FrameworkElementFactory。可見,模板不是直接創建可視化對象,而是通過一個工廠類來實例化。畢竟用於模板的可視化樹是在用到時才創建的。

這麼看來,對於控制項、常見元素,用 XAML 和用純代碼寫差不多,而模板用代碼寫就複雜一些。所以,比較好的方法是把控制項樣式、模板都放到外部的 XAML 文件中,再在程式中載入(就像老周上一篇水文那樣)。要改 UI 你直接改 XAML 文件就行了,程式不用重新編譯。

說一下用法。

1、調用 FrameworkElementFactory 類的構造函數,可以直接用 XAML 文本初始化,也可以指定一個 Type,讓工廠類自動實例化。

2、a:要設置某個屬性的值,用 SetValue 方法;

      b:要為某個屬性設置數據綁定,請用 SetBinding 方法;

      c:要引用資源中的東東,請用 SetResourceReference 方法。

3、調用 AppendChild 方法可以把另一個 FrameworkElementFactory 對象添加當前對象的子級。這種方法可以構建 N 個層次的邏輯樹。

4、AddHandler、RemoveHandler 為對象添加或刪除事件處理方法。

 

老周下麵要用的這個例子,是一個控制項庫。在新建項目時,可以直接用 WPF 控制項庫模板。

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net7.0-windows</TargetFramework>
    <Nullable>enable</Nullable>
    <UseWPF>true</UseWPF>
  </PropertyGroup>

</Project>

我們這裡不用 XAML 文件,所以,Themes 目錄可以刪除。然後就像寫普通類庫一樣,定義控制項類,從 Control 類派生。

 public class VVControl : Control
 {
       ……
 }

這個控制項沒什麼實用價值,純屬娛樂。控制項模板裡面放一個 StackPanel,水平排列,然後排三個圓。滑鼠點第一個圓時,只有第一個圓的背景色會變;點擊第二個圓時,第一、二個圓的背景色都變;點擊第三個圓時,三個圓的背景色都會變。

 // 根元素
 FrameworkElementFactory rootFac = new(typeof(StackPanel));
 // 設置方向
 rootFac.SetValue(StackPanel.OrientationProperty, Orientation.Horizontal);

這個是模板中的根元素,StackPanel 面板,方向水平。然後我們弄三個圓,圓可以用 Ellipse 類來做,寬度和高度相等就是正圓了。

// 圓的寬度和高度
const double ELL_SIZE = 35.0d;
const double ELL_MARGIN = 6.5d;
// 輪廓大小
const double ELL_STROKEW = 2.0d;

// 子元素是三個圈
FrameworkElementFactory ellip1 = new(typeof(Ellipse), "ellip1");
// 設置寬度和高度
ellip1.SetValue(Shape.WidthProperty, ELL_SIZE);
ellip1.SetValue(Shape.HeightProperty, ELL_SIZE);
// 邊距
ellip1.SetValue(Shape.MarginProperty, new Thickness(ELL_MARGIN));
ellip1.SetValue(Shape.StrokeThicknessProperty, ELL_STROKEW);
// 這兩個屬性要綁定
ellip1.SetBinding(Shape.StrokeProperty, fgbind);
// 把子元素追加到樹中
rootFac.AppendChild(ellip1);

FrameworkElementFactory ellip2 = new(typeof(Ellipse), "ellip2");
ellip2.SetValue(Shape.WidthProperty, ELL_SIZE);
ellip2.SetValue(Shape.HeightProperty, ELL_SIZE);
ellip2.SetValue(Shape.MarginProperty, new Thickness(ELL_MARGIN));
ellip2.SetBinding(Shape.StrokeProperty, fgbind);
ellip2.SetValue(Shape.StrokeThicknessProperty, ELL_STROKEW);
rootFac.AppendChild(ellip2);

FrameworkElementFactory ellip3 = new(typeof(Ellipse), "ellip3");
ellip3.SetValue(Shape.WidthProperty, ELL_SIZE);
ellip3.SetValue(Shape.HeightProperty, ELL_SIZE);
ellip3.SetValue(Shape.MarginProperty, new Thickness(ELL_MARGIN));
ellip3.SetBinding(Shape.StrokeProperty, fgbind);
ellip3.SetValue(Shape.StrokeThicknessProperty, ELL_STROKEW);
rootFac.AppendChild(ellip3);

這樣,控制項模板就構建好了,下麵創建 ControlTemplate,並賦值給當前控制項的 Template 屬性。

 ControlTemplate temp = new(this.GetType());
 temp.VisualTree = rootFac;
 this.Template = temp;

模板中的三個圓都有命名的,比如

FrameworkElementFactory ellip2 = new(typeof(Ellipse), "ellip2");

FrameworkElementFactory 構造函數的第二個參數可以為元素分配一個 Name。後面咱們在控制項的邏輯處理中要訪問這三個圓,所以給它們命名。

定義一個 LoadExtXaml 方法,傳入文件名,這樣方便動態載入 XAML 文件。

 public void LoadExtXaml(string file)
 {
     using FileStream input = File.OpenRead(file);
     this.Resources = (ResourceDictionary)XamlReader.Load(input);
     // 從資源加獲取畫刷
     this.Background = (SolidColorBrush)Resources["background"];
     this.BorderBrush = (SolidColorBrush)Resources["bordercolor"];
 }

XAML 文件單獨放到類庫外,方便直接修改,不重新編譯。

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <SolidColorBrush x:Key="background" Color="Green"/>
    <SolidColorBrush x:Key="bordercolor" Color="Red"/>
</ResourceDictionary>

這主要是背景、前景色的畫刷,常用的可能有字體啊、背景圖片啊什麼的,這些內空修改的概率大,全扔到外部 XAML 文件中。為了可以給控制項”換皮膚“,咱們也可以再弄一個 XAML 文件,也是放到程式外。

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <SolidColorBrush x:Key="background" Color="Blue"/>
    <SolidColorBrush x:Key="bordercolor" Color="DeepPink"/>
</ResourceDictionary>

如果你有 100 套皮膚,那就弄 100 個 XAML 文件就行了。最好建個文件夾,把 XAML 全放進去。XAML 文件可以用專門的命名方式。比如 myStyle-<主題名稱>.xaml 這樣,方便在代碼中識別。你甚至可以寫代碼直接遍歷這個目錄下的 XAML 文件,然後在程式視窗上動態生成菜單,讓用戶選擇皮膚,然後載入對應的 XAML 文件。豈不美哉!

 

好了,現在控制項有了用純代碼搞的模板,又可載入外部資源了。接下來要重寫 OnApplyTemplate 方法,當控制項套用完模板後就會調用這個方法,我們在這個地方就可以讀出模板裡面命名的三個 Ellipse 對象了。

Ellipse _ep1, _ep2, _ep3;
// 透明畫刷
SolidColorBrush _defaultBrush = new(Colors.Transparent);
……

public override void OnApplyTemplate()
{
    base.OnApplyTemplate();
    _ep1 = (Ellipse)GetTemplateChild("ellip1");
    _ep2 = (Ellipse)GetTemplateChild("ellip2");
    _ep3 = (Ellipse)GetTemplateChild("ellip3");
    _ep1.Fill = _ep2.Fill = _ep3.Fill = _defaultBrush;
    _ep1.MouseDown += OnEllipseMouseDown;
    _ep2.MouseDown += OnEllipseMouseDown;
    _ep3.MouseDown += OnEllipseMouseDown;
    // 雙擊恢復預設填充顏色
    this.MouseDoubleClick += (_, _) =>
    {
        _ep1.Fill = _ep2.Fill = _ep3.Fill = _defaultBrush;
    };
}

要將模板中的對象擼出來不要調用 FindName 方法,這個方法只查找當前對象的子級,不是包括模板裡面的。而要用 GetTemplateChild 方法,這個才是搜索模板的。

下麵就是處理 MouseDown 的方法。

private void OnEllipseMouseDown(object sender, MouseButtonEventArgs e)
{
    if(e.OriginalSource == _ep1)
    {
        _ep1.Fill = Background;
        _ep2.Fill = _ep3.Fill = _defaultBrush;
    }
    else if(e.OriginalSource == _ep2)
    {
        _ep1.Fill = _ep2.Fill = Background;
        _ep3.Fill = _defaultBrush;
    }
    else if(e.OriginalSource == _ep3)
    {
        _ep1.Fill = _ep2.Fill = _ep3.Fill = Background;
    }
    else
    {
        _ep1.Fill = _ep2.Fill = _ep3.Fill = _defaultBrush;
    }
}

 

控制項庫搞好了,然後咱們得用用,看正不正常。添加一個 WPF 應用程式項目。

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>net7.0-windows</TargetFramework>
    <Nullable>enable</Nullable>
    <UseWPF>true</UseWPF>
  </PropertyGroup>

</Project>

你會發現,其實 WPF應用程式 和 WPF 控制項庫的項目文件差不多,區別是多了 OutputType 為 Winexe 的屬性罷了。

引用咱們剛剛做好的控制項庫項目。

<ItemGroup>
  <ProjectReference Include="..\CustControl\CustControl.csproj" />
</ItemGroup>

 

寫視窗類。

public class MyWindow : Window
{
    public MyWindow()
    {
        InitUI();
    }

    private void InitUI()
    {
        NameScope.SetNameScope(this, new NameScope());
        DockPanel root = new();
        root.LastChildFill = true;
        this.Content = root;
        // 有兩個按鈕,用來選擇主題
        StackPanel btnPanel = new()
        {
            Orientation = Orientation.Horizontal
        };
        Button btnStyle1 = new Button
        {
            Content = "主題1"
        };
        Button btnStyle2 = new Button
        {
            Content = "主題2"
        };
        btnPanel.Children.Add(btnStyle1);
        btnPanel.Children.Add(btnStyle2);
        root.Children.Add(btnPanel);
        DockPanel.SetDock(btnPanel, Dock.Bottom);
        btnStyle1.Click += OnStyle1Click;
        btnStyle2.Click += OnStyle2Click;

        VVControl cust = new("mycc\\style.a.xaml");
        RegisterName("myCust", cust);
        root.Children.Add(cust);
    }

    private void OnStyle2Click(object sender, RoutedEventArgs e)
    {
        VVControl? cc = FindName("myCust") as VVControl;
        if(cc != null)
        {
            cc.LoadExtXaml("mycc\\style.b.xaml");
        }
    }

    private void OnStyle1Click(object sender, RoutedEventArgs e)
    {
        VVControl? c = FindName("myCust") as VVControl;
        if(c != null)
        {
            c.LoadExtXaml("mycc\\style.a.xaml");
        }
    }
}

Main 入口點。

[STAThread]
static void Main(string[] args)
{
    Application app = new Application();
    MyWindow win = new MyWindow();
    win.Title = "示常式序";
    win.Width = 350;
    win.Height = 300;
    app.Run(win);
}

在生成的主程式的.exe 所在目錄下創建 mycc 目錄,把前面那兩個 XAML 文件放進去,就完功了。

 

但你會發現,換主題時,圓的背景色不會自動換,要等單擊事件後才變,而圓的輪廓是能及時換色的。這是因為 Fill 屬性沒有進行綁定,是在處理滑鼠按下事件時用代碼賦值的,所以不會自動更新。

至於 DataTemplate,和 ControlTemplate 一樣的,也是通過 FrameworkElementFactory 類構建對象樹。老周就不重覆說了。數據模板和控制項模板本來就是同一玩意兒,只是它們的角色不一樣而已。

如果你的程式要通過代碼來計算,動態得到 UI 相關屬性的話,那用純代碼寫較方便;如果不是的話,可以把一些資源放到程式外,這樣你想改 的時候隨便改,代碼不用多次編譯。

 

下麵咱們弄個內外結合的方案。即控制項庫使用內置的XAML,但像邊框、背景、字體等,放到外部的文件中。

新建 WPF 控制項庫項目,我們做個簡單控制項。

Themes/Generic.xaml:

<ResourceDictionary  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       xmlns:import="clr-namespace:GuaGuaControlLib">
    <Style TargetType="{x:Type import:MyControl}">
        <Setter Property="BorderBrush" Value="{DynamicResource bdColor}"/>
        <Setter Property="Foreground" Value="{DynamicResource fgColor}"/>
        <Setter Property="Background" Value="{DynamicResource bgColor}"/>
        <Setter Property="Margin" Value="4.5"/>
        <Setter Property="BorderThickness" Value="1,1.5"/>
        <Setter Property="FontSize" Value="{DynamicResource fontSize}"/>
        <Setter Property="FontFamily" Value="{DynamicResource fontFamily}"/>
        <Setter Property="HorizontalContentAlignment" Value="Center"/>
        <Setter Property="VerticalContentAlignment" Value="Center"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type import:MyControl}">
                    <Border Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}">
                        <TextBlock FontFamily="{TemplateBinding FontFamily}"
                                   FontSize="{TemplateBinding FontSize}"
                                   Margin="{TemplateBinding Padding}"
                                   Foreground="{TemplateBinding Foreground}"
                                   HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                   VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                               Text="{TemplateBinding Text}"/>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

MyControl.cs

[assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)]

namespace GuaGuaControlLib
{
    public class MyControl : Control
    {
        public static readonly DependencyProperty TextProperty;

        static MyControl()
        {
            // 重寫樣式鍵的依賴屬性元數據
            DefaultStyleKeyProperty.OverrideMetadata(
                    typeof(MyControl),
                    new FrameworkPropertyMetadata(typeof(MyControl))
                );
            // 註冊依賴屬性
            TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(MyControl), new FrameworkPropertyMetadata(string.Empty));
        }

        // 封裝屬性
        public string Text
        {
            get => (string)GetValue(TextProperty);
            set => SetValue(TextProperty, value);
        }

        public MyControl()
        {
        }

    }
}

有五個資源咱們放到項目外面,這裡得用動態資源才能正確引用,用靜態資源會報錯,目前老周未找到解決方法。

 

下麵這個 XAML 文件不包含在項目內,不會參與生成。

res/cust.xaml:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:sys="clr-namespace:System;assembly=mscorlib">
    <SolidColorBrush x:Key="bdColor" Color="blue"/>
    <SolidColorBrush x:Key="bgColor" Color="red"/>
    <SolidColorBrush x:Key="fgColor" Color="LightBlue"/>
    <sys:Double x:Key="fontSize">25.0</sys:Double>
    <FontFamily x:Key="fontFamily">華文彩雲</FontFamily>
</ResourceDictionary>

這五個 Key 對應被引用的五個資源項。

 

添加 WPF 應用程式項目,並引用 MyControl 所在項目。

<ItemGroup>
  <ProjectReference Include="..\GuaGuaControlLib\GuaGuaControlLib.csproj" />
</ItemGroup>

從 Window 類派生自定義視窗類。

 class MyWindow : Window
 {
     public MyWindow()
     {
         // 載入外部資源
         using var fs = File.OpenRead("res\\cust.xaml");
         // 合併資源字典
         Resources.MergedDictionaries.Add((ResourceDictionary)XamlReader.Load(fs));
         MyControl cc = new();
         cc.Text = "小約翰可汗";
         Grid root = new();
         root.Children.Add(cc);
         Content = root;
     }
 }
class Program
{
    [STAThread]
    static void Main(string[] args)
    {
        Application myapp = new Application();

        MyWindow mainWin = new MyWindow();
        mainWin.Title = "外部資源";
        mainWin.Width = 242;
        mainWin.Height = 199;
        myapp.Run(mainWin);
    }
}

這裡咱們採用合併資源字典的方式載入 XAML 文件。如果主資源中有定義的內部對象,用合併字典的方式可以保證主資源中的對象不會被覆蓋。

運行看一下。

打開外部的 cust.xaml 文件,咱們改一下顏色和字體,並保存。

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:sys="clr-namespace:System;assembly=mscorlib">
    <SolidColorBrush x:Key="bdColor" Color="blue"/>
    <SolidColorBrush x:Key="bgColor" Color="darkblue"/>
    <SolidColorBrush x:Key="fgColor" Color="LightBlue"/>
    <sys:Double x:Key="fontSize">25.0</sys:Double>
    <FontFamily x:Key="fontFamily">華文行楷</FontFamily>
</ResourceDictionary>

不要重新生成項目,直接運行程式。

嗯,這樣就方便很多了。

 

===================================================================================

關於純代碼寫 WPF 以及載入外部 XAML 以方便改程式,老周一口氣寫完了這三篇水文。下麵老周就做一個膚淺的總結吧。

先說說為什麼會產生這一系列”奇葩“想法。主要有這兩個因素:

1、對界面做一些參數的修改(如字體、顏色、背景圖什麼的)又要重新生成項目確實麻煩;

2、Qt 的 QSS 和 QML 既可以編譯進資源中,也可以放在外部引用,也容易修改。所以我在想,WPF 項目也應該這樣搞。

老周正在虐待的這個破項目比較雜,界面主視窗是 Qt 做的,一些左邊欄,右邊欄子視窗是 Win32 寫的。操作員設置視窗是別人用 WPF 做的。exe 文件都好幾個(以前寫代碼那貨肯定東抄一塊,西抄一塊來的)。所以,用 Win32 API 寫的和 WPF 寫的程式,在入口函數時直接創建子進程,讓它們運行,然後獲取視窗的句柄,套在 Qt 的 Widget 中,再懟到主視窗上。目前沒什麼問題,運行之後,外行人看不出來是幾個東東拼接出來的。忽悠過去就完事了,誰還管它 100 年呢。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • pymongo模塊是python操作mongo數據的第三方模塊,記錄一下常用到的簡單用法。 **首先需要連接資料庫:** - MongoClient():該方法第一個參數是資料庫所在地址,第二個參數是資料庫所在的埠號 - authenticate():該方法第一個參數是資料庫的賬號,第二個參數是數 ...
  • # Go 語言之 Viper 的使用 ## Viper 介紹 [Viper](https://github.com/spf13/viper): ### 安裝 ```bash go get github.com/spf13/viper ``` ### Viper 是什麼? Viper 是一個針對 Go ...
  • 以WebMvcAutoConfiguration自動配置的原理為例,SpringBoot內部對大量的第三方庫或Spring內部庫進行了預設配置,這些配置是否生效,取決於我們是否引入了對應庫所需的依賴,如果有那麼預設配置就會生效。如果引入springboot-starter-web那麼對應的web配置 ...
  • `NumPy`(Numerical Python)是一個`Python`庫,主要用於高效地處理多維數組和矩陣計算。它是科學計算領域中使用最廣泛的一個庫。 在`NumPy`中,**數組**是最核心的概念,用於存儲和操作數據。 `NumPy`數組是一種多維數組對象,可以存儲相同類型的元素,它支持高效的數 ...
  • 一、簡介 官網: https://spring.io/projects/spring-framework#overview 官方下載工具: https://repo.spring.io/release/org/springframework/spring/ github下載: https://git ...
  • # 頁面預覽 ## 預約掛號 - 根據預約周期,展示可預約日期,根據有號、無號、約滿等狀態展示不同顏色,以示區分 - 可預約最後一個日期為即將放號日期 - 選擇一個日期展示當天可預約列表 ![image-20230227202834422](https://s2.loli.net/2023/06/1 ...
  • # 一、緒論 ## 1.1 基本概念 1. 加速比:表示加速效果。單個處理器運行花費時間 / P個處理器運行花費時間;$S=\frac{T(1)}{T(p)}$ 2. 效率:$E = \frac{S}{p} = \frac{T(1)}{T(p)\times p}$ 3. 開銷:$C=T(p)\tim ...
  • 1、簡介 SiftingAppender 可根據給定的運行時屬性將日誌分離或篩選。例如,SiftingAppender 可以根據用戶會話將日誌事件分開,以便不同用戶生成的日誌進入不同的日誌文件,每個用戶一個日誌文件。SiftingAppender 有兩個屬性: timeout SiftingAppe ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...