UWP WinUI 製作一個路徑矢量圖標按鈕樣式入門

来源:https://www.cnblogs.com/lindexi/p/18288632
-Advertisement-
Play Games

在 Visual Studio 中,至少可以創建三種不同類型的類庫: 類庫(.NET Framework) 類庫(.NET 標準) 類庫 (.NET Core) 雖然第一種是我們多年來一直在使用的,但一直感到困惑的一個主要問題是何時使用 .NET Standard 和 .NET Core 類庫類型。 ...


本文將告訴大家如何在 UWP 或 WinUI3 或 UNO 里,如何製作一個路徑按鈕。路徑按鈕就是使用幾何路徑輪廓表示內容的按鈕,常見於各種圖標按鈕,或 svg 系貼圖矢量圖按鈕

在網上有非常多矢量圖庫,其中免費的圖庫也非常多,比如 https://www.iconfont.cn/ 等等。在咱的應用程式裡面,可以使用這些矢量圖作為按鈕的圖標,從而更好的進行表意,讓界面有更好的設計。使用矢量圖還自然帶有縮放時依然清晰的功能

最為簡單的製作方式就是在按鈕裡面存放一個 Path 作為內容,比如做一個簡單的路徑矢量圖標按鈕

    <Button HorizontalAlignment="Center" VerticalAlignment="Center">
      <Path Stroke="Black" StrokeThickness="1" Data="M5,5L15,15L5,25"></Path>
    </Button>

可以看到簡單的幾行代碼就可以實現一個圖標按鈕的功能了。不過哩作為有追求的開發者,可不能像在樹上的小貓一樣,咱還需要多加一些需求。比如我希望滑鼠移動到按鈕上的時候,按鈕可以變色,比如說我感覺上面的重覆代碼多了,即我有多個圖標按鈕都有大量相似的代碼,能不能做一個樣式實現這些功能?當然是可以的啦

先在一個資源裡面定義按鈕的樣式,資源可以放在自己的應用業務代碼 xaml 文件裡面,也可以單獨做一個資源字典。本文為了簡單,就放在 MainPage.xaml 裡面了。如果大家想要放在資源字典裡面,別忘了引用資源字典哦

    <Style x:Key="Style.Button.PathButtonStyle" TargetType="Button">
       ...
    </Style>

如上面代碼,就定義了一個名為 Style.Button.PathButtonStyle 的代碼樣式。這樣的樣式命名方法是我習慣用的,因為如此可以方便一級級點下去,特別在有 ReSharper 的幫助下,會更加好用,在樣式特別多的時候,這樣寫能夠和 ReSharper 更好的進行配合

這樣的樣式,可以應用到按鈕代碼上,如下麵代碼

   <Button Style="{StaticResource Style.Button.PathButtonStyle}"
   	 .../>

此樣式都是給路徑圖標按鈕製作,可以製作非常明確的按鈕樣式實現。對於 xaml 的界面樣式實現的編碼思路有些會和 C# 不一樣,即不追求抽象性,有很多界面邏輯都是越具體越好,且允許有一些代碼是重覆的。核心追求就是讓界面代碼在看的時候可以更好的和界面效果聯繫起來,按照界面組織的方式走而不是按照邏輯的組織方式走。且有些界面效果是追求界面像,而不追求邏輯合理,即只要界面像就好更重要,當然,能兩者都兼顧那是最好的。放心,本文提供的方法還是兩者都兼顧的。那是否只有本文介紹的附加屬性的方法才是最佳實踐?當然不是啦,只不過這個方法我用的順手而已

    <Style x:Key="Style.Button.PathButtonStyle" TargetType="Button">
      <Setter Property="Template">
        <Setter.Value>
          <ControlTemplate TargetType="Button">
            <Grid x:Name="RootGrid" Background="{TemplateBinding Background}">
              <Path x:Name="ButtonContentPath" StrokeThickness="1" Stroke="Black" Data="M5,5L15,15L5,25"></Path>
            </Grid>
          </ControlTemplate>
        </Setter.Value>
      </Setter>
    </Style>

如上面代碼,即定義了一個圖標按鈕的樣式,也寫明瞭圖標按鈕的內容,應用此樣式的按鈕即可顯示出也如上圖的效果

樣式自然是追求一定的通用性的,上面代碼只能顯示固定的路徑圖標,自然不符合咱的需求。能否讓 ButtonContentPath 的 Data 參與業務定製?自然是可以的,接下來咱使用簡單的附加屬性來解決此問題

通過附加屬性的方式,既可以用在 UWP 等框架上,同樣在 WPF 裡面也是可以使用的,畢竟都是相同系列的框架

在後臺 cs 代碼裡面定義一個名為 ButtonHelper 的類型,將在這個類型裡面定義附加屬性,實現代碼如下

public class ButtonHelper
{
    public static readonly DependencyProperty ButtonPathProperty = DependencyProperty.RegisterAttached(
        "ButtonPath", typeof(string), typeof(ButtonHelper), new PropertyMetadata(default(string)));
    
    public static void SetButtonPath(DependencyObject element, string value)
    {
        element.SetValue(ButtonPathProperty, value);
    }
    
    public static string GetButtonPath(DependencyObject element)
    {
        return (string)element.GetValue(ButtonPathProperty);
    }
    
    ... // 忽略其他代碼
}

如此即可在樣式裡面進行綁定 Data 的內容,核心代碼如下

<Path x:Name="ButtonContentPath" StrokeThickness="2" Stroke="#FF666666" Data="{Binding  RelativeSource={RelativeSource TemplatedParent},Path=(local:ButtonHelper.ButtonPath)}"></Path>

如果大家看了本文的內容不知道代碼寫在哪,可以到本文末尾獲取所有代碼的下載方法,拉取我的代碼跑跑看

通過以上代碼,可以看到使用 (local:ButtonHelper.ButtonPath) 將 Data 綁定到 ButtonHelper 的 ButtonPath 附加屬性上,屬性源是通過 RelativeSource={RelativeSource TemplatedParent} 指定的,在這裡就是按鈕本身。以上代碼的 local: 的 local 表示的 xaml 命名空間,這是因為我將 ButtonHelper 放在和 MainPage 相同的命名空間上,於是就剛好就是 local 的值,如果大家放在其他命名空間,還請在 VisualStudio 的幫助下進行命名空間引用 。以上代碼的細節在於必須通過 RelativeSource 和 TemplatedParent 指定,且使用 Binding 進行綁定,不能通過 TemplateBinding 和 Source 指定綁定

應用以上樣式的按鈕,需要在按鈕上給 ButtonHelper 的 ButtonPath 附加屬性進行賦值,如以下代碼

    <Button Style="{StaticResource Style.Button.PathButtonStyle}"

local:ButtonHelper.ButtonPath="M5,5L15,15L5,25"
     .../>

運行代碼也可以看到大概如上圖的效果,也就是本文以上提供的三個方式都是實現相同的一個按鈕效果。可以看到第一個代碼最簡單,最後一個代碼最有通用性,可以將更多的圖標按鈕使用樣式減少重覆的代碼

那接下來給樣式提出更多的要求,如滑鼠移動到按鈕上方時,修改按鈕的圖標顏色

對於 Path 元素來說,可以通過 Stroke 和 StrokeThickness 分別修改輪廓顏色畫刷和輪廓線條粗細,可以使用 Fill 屬性修改填充畫刷。在滑鼠移動到按鈕上方,即 PointerOver 時,通過設置輪廓畫刷或填充畫刷即可修改按鈕的圖標顏色

期望在滑鼠移動到按鈕上方,即 PointerOver 時,設置輪廓畫刷或填充畫刷,需要配合 VisualStateManager 提供的多個視覺狀態,在每個視覺狀態下給屬性賦值或製作動畫

最常用的 VisualStateManager 的 VisualStateGroup 是 CommonStates 組,基礎代碼組成如下

              <VisualStateManager.VisualStateGroups>
                <VisualStateGroup x:Name="CommonStates">
                  <VisualState x:Name="Normal">
                    <!-- 正常狀態 -->
                  </VisualState>
                  <VisualState x:Name="PointerOver">
                   <!-- 滑鼠移動到控制項上,即 WPF 的 Hover 效果 -->
                  </VisualState>
                  <VisualState x:Name="Pressed">
                    <!-- 滑鼠按下的狀態,或叫點擊的狀態 -->
                  </VisualState>
                </VisualStateGroup>
              </VisualStateManager.VisualStateGroups>

這裡有一些細節事項:

  • 由於 VisualStateManager 必須放在容器裡面,因此這裡必須需要有一個容器控制項住 VisualStateManager 的代碼。簡單的容器就是如 Grid 等控制項,想省一點資源的話,可以用 Border 代替 Grid 做容器
  • 一般情況下,第一個狀態是 Normal 狀態,裡面啥都不用做,啥都不用做可以清空其他的 VisualState 的狀態。正常狀態需要放在第一個

開始編寫正式的代碼之前,先複習一下 VisualStateManager 的用法,如下麵的代碼,既可以在 VisualState 裡面使用 Setter 修改屬性。也可以使用 Storyboard 做動畫修改屬性。做動畫的方式可以比較柔和,有漸變的效果

  <Page.Resources>
    <Style x:Key="Style.Button.FooButtonStyle" TargetType="Button">
      <Setter Property="Template">
        <Setter.Value>
          <ControlTemplate TargetType="Button">
            <Grid x:Name="RootGrid" Background="{TemplateBinding Background}">
              <!-- 由於 VisualStateManager 必須放在容器裡面,因此這裡必須需要有一個容器 想省一點的話,可以用 Border 代替 Grid 做容器-->
              <VisualStateManager.VisualStateGroups>
                <VisualStateGroup x:Name="CommonStates">
                  <VisualState x:Name="Normal">
                    <Storyboard>
                      <!--啥都不用做,清空狀態即可-->
                      <!-- 正常狀態需要放在第一個 -->
                    </Storyboard>
                  </VisualState>
                  <VisualState x:Name="PointerOver">
                    <!-- Hover 效果 -->
                    <VisualState.Setters>
                      <Setter Target="ButtonContentPath.Stroke" Value="Transparent"></Setter>
                      <Setter Target="ButtonContentPath.Fill" Value="Blue"></Setter>
                    </VisualState.Setters>
                  </VisualState>
                  <VisualState x:Name="Pressed">
                    <!-- 按下狀態 -->
                    <Storyboard>
                      <!-- 顏色用 ColorAnimation 也可以 -->
                      <!-- <ColorAnimation To=""></ColorAnimation> -->
                      <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ButtonContentPath" Storyboard.TargetProperty="Stroke" >
                        <DiscreteObjectKeyFrame KeyTime="0" Value="Transparent"/>
                      </ObjectAnimationUsingKeyFrames>

                      <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ButtonContentPath" Storyboard.TargetProperty="Fill" >
                        <DiscreteObjectKeyFrame KeyTime="0" Value="#FF666666"/>
                      </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                  </VisualState>
                  <VisualState x:Name="Disabled">
                    <!-- 不可用的狀態 -->
                  </VisualState>
                </VisualStateGroup>
              </VisualStateManager.VisualStateGroups>

              <Path x:Name="ButtonContentPath" StrokeThickness="2" Stroke="#FF666666" Data="M7,15C6.85289858,15.5677816,6.85289858,16.4322348,7,17L22,29C22.7348015,29.3762198,24,28.8227297,24,28L24,4C24,3.1772867,22.7348015,2.62379657,22,3L7,15z"></Path>
            </Grid>
          </ControlTemplate>
        </Setter.Value>
      </Setter>
    </Style>

  </Page.Resources>
  <StackPanel
    HorizontalAlignment="Center"
    VerticalAlignment="Center">
    <Border BorderBrush="Black" BorderThickness="0">
      <Button Style="{StaticResource Style.Button.FooButtonStyle}"
            Background="Transparent" Padding="0">

      </Button>
    </Border>
  </StackPanel>

以上代碼的細節點在於想要讓 VisualStateManager 的 VisualStateGroups 生效,必須放在容器裡面,直接寫在 ControlTemplate 下麵是不行的。第一個 Normal 的 VisualState 需要放在最前面,裡面可以不寫任何的代碼,將會自動清空狀態

也如上面代碼,設置屬性的值時候,既可以使用 Setters 的方式,也可以使用動畫的方式。使用 Setters 的代碼比較短,如下麵代碼

 <VisualState x:Name="PointerOver">
   <!-- Hover 效果 -->
   <VisualState.Setters>
     <Setter Target="ButtonContentPath.Stroke" Value="Transparent"></Setter>
     <Setter Target="ButtonContentPath.Fill" Value="Blue"></Setter>
   </VisualState.Setters>
 </VisualState>

使用 Setters 時不需要管 Property 屬性,只需要保證 Target 是 對象.屬性 的寫法就好了

使用動畫的例子如下

 <VisualState x:Name="Pressed">
   <!-- 按下狀態 -->
   <Storyboard>
     <!-- 顏色用 ColorAnimation 也可以 -->
     <!-- <ColorAnimation To=""></ColorAnimation> -->
     <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ButtonContentPath" Storyboard.TargetProperty="Stroke" >
       <DiscreteObjectKeyFrame KeyTime="0" Value="Transparent"/>
     </ObjectAnimationUsingKeyFrames>

     <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ButtonContentPath" Storyboard.TargetProperty="Fill" >
       <DiscreteObjectKeyFrame KeyTime="0" Value="#FF666666"/>
     </ObjectAnimationUsingKeyFrames>
   </Storyboard>
 </VisualState>

動畫代碼比較多,但是可以實現比較柔和的效果。因為 Setters 是立刻變化的,動畫可以實現慢慢變化。對於視覺效果比較大的範圍,推薦使用動畫

具體一個控制項有哪些 VisualState 可以設置,需要查閱文檔,詳細請看: https://learn.microsoft.com/en-us/uwp/api/windows.ui.xaml.visualstate

瞭解基礎用法之後,咱就可以繼續在 ButtonHelper 裡面定義滑鼠移動到按鈕上的邊框輪廓顏色畫刷附加屬性,如下麵代碼

public class ButtonHelper
{
    public static readonly DependencyProperty PointerOverStrokeBrushProperty = DependencyProperty.RegisterAttached(
        "PointerOverStrokeBrush", typeof(Brush), typeof(ButtonHelper), new PropertyMetadata(default(Brush)));
    
    public static void SetPointerOverStrokeBrush(DependencyObject element, Brush value)
    {
        element.SetValue(PointerOverStrokeBrushProperty, value);
    }
    
    public static Brush GetPointerOverStrokeBrush(DependencyObject element)
    {
        return (Brush)element.GetValue(PointerOverStrokeBrushProperty);
    }
}

定義完成附加屬性,嘗試在 XAML 裡面使用這個屬性。正常的使用方法是會在樣式裡面,給定附加屬性初值的。為什麼不在附加屬性定義的時候,寫附加屬性預設值?這是因為不同的樣式一般都會有樣式自身期望的初值,因此作為樣式使用的附加屬性,比較少會配置預設值。但也不是不能,取決於你的開森

    <Style x:Key="Style.Button.PathButtonStyle" TargetType="Button">
      <Setter Property="local:ButtonHelper.PointerOverStroke" Value="#FF666666"/>
      ...
    </Style>

將此 PointerOverStroke 在 PointerOver 賦值給到按鈕的 Path 上,代碼如下,以下代碼使用 Setter 的方式賦值,代碼看起來比較短

                  <VisualState x:Name="PointerOver">
                    <VisualState.Setters>
                      <Setter Target="ButtonContentPath.Stroke" Value="{Binding RelativeSource={RelativeSource TemplatedParent},Path=(local:ButtonHelper.PointerOverStrokeBrush)}"></Setter>
                    </VisualState.Setters>
                  </VisualState>

如此即可完成樣式的對滑鼠移動到按鈕上,按鈕使用附加屬性配置的顏色的定義

按鈕可以通過 PointerOverStrokeBrush 附加屬性定義按鈕期望滑鼠移動到按鈕上的顏色畫刷,如以下代碼

    <Button Style="{StaticResource Style.Button.PathButtonStyle}"

local:ButtonHelper.ButtonPath="M5,5L15,15L5,25"
            local:ButtonHelper.PointerOverStrokeBrush="Blue">

    </Button>

可以看到,在完成樣式定義的基礎上,只需簡單的代碼就可以讓按鈕工作起來了

如果剛好有一組按鈕都需要做相同的滑鼠移動到按鈕上的 Hover 顏色畫刷更改,可以再定義一個新的樣式,繼承 Style.Button.PathButton 樣式,如以下代碼

    <Style x:Key="Style.Button.SlideButtonStyle" TargetType="Button" BasedOn="{StaticResource Style.Button.PathButton}">
        <Setter Property="Width" Value="50"></Setter>
        <Setter Property="Height" Value="50"></Setter>
        <Setter Property="local:ButtonHelper.PointerOverStrokeBrush" Value="#FF996666"/>
    </Style>

如此可以在不影響閱讀界面代碼的前提下,減少界面代碼的重覆量,也能讓界面代碼編寫更加方便

本文定義的 Style.Button.PathButton 按鈕樣式的代碼如下

    <Style x:Key="Style.Button.PathButtonStyle" TargetType="Button">
      <Setter Property="Background" Value="Transparent"></Setter>
      <Setter Property="HorizontalAlignment" Value="Center"></Setter>
      <Setter Property="local:ButtonHelper.PointerOverStrokeBrush" Value="#FF666666"/>
      <Setter Property="VerticalAlignment" Value="Center"></Setter>
      <Setter Property="Template">
        <Setter.Value>
          <ControlTemplate TargetType="Button">
            <Grid x:Name="RootGrid" Background="{TemplateBinding Background}">
              <VisualStateManager.VisualStateGroups>
                <VisualStateGroup x:Name="CommonStates">
                  <VisualState x:Name="Normal">

                  </VisualState>
                  <VisualState x:Name="PointerOver">
                    <VisualState.Setters>
                      <Setter Target="ButtonContentPath.Stroke" Value="{Binding RelativeSource={RelativeSource TemplatedParent},Path=(local:ButtonHelper.PointerOverStrokeBrush)}"></Setter>
                    </VisualState.Setters>
                  </VisualState>
                  <VisualState x:Name="Pressed">

                  </VisualState>
                </VisualStateGroup>
              </VisualStateManager.VisualStateGroups>
              <Path x:Name="ButtonContentPath" StrokeThickness="2" Stroke="#FF666666" Data="{Binding RelativeSource={RelativeSource TemplatedParent},Path=(local:ButtonHelper.ButtonPath)}"></Path>
            </Grid>
          </ControlTemplate>
        </Setter.Value>
      </Setter>
    </Style>

本文代碼放在 githubgitee 上,可以使用如下命令行拉取代碼

先創建一個空文件夾,接著使用命令行 cd 命令進入此空文件夾,在命令行裡面輸入以下代碼,即可獲取到本文的代碼

git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin 2eb5da7c4a63d65e1a2424ca40e2ae94f5da7549

以上使用的是 gitee 的源,如果 gitee 不能訪問,請替換為 github 的源。請在命令行繼續輸入以下代碼,將 gitee 源換成 github 源進行拉取代碼

git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git
git pull origin 2eb5da7c4a63d65e1a2424ca40e2ae94f5da7549

獲取代碼之後,進入 UnoDemo/PathButtonDemo 文件夾,即可獲取到源代碼

更多 UWP 或 WinUI3 或 UNO 開發教程,請參閱 博客導航

博客園博客只做備份,博客發佈就不再更新,如果想看最新博客,請訪問 https://blog.lindexi.com/

如圖片看不見,請在瀏覽器開啟不安全http內容相容

知識共用許可協議
本作品採用知識共用署名-非商業性使用-相同方式共用 4.0 國際許可協議進行許可。歡迎轉載、使用、重新發佈,但務必保留文章署名[林德熙](https://www.cnblogs.com/lindexi)(包含鏈接:https://www.cnblogs.com/lindexi ),不得用於商業目的,基於本文修改後的作品務必以相同的許可發佈。如有任何疑問,請與我[聯繫](mailto:[email protected])。
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 大家好,我是碼農先森。 回想起以前用模版渲染數據的歲月,那時都沒有 API 介面開發的概念。PHP 服務端和前端 HTML、CSS、JS 代碼混合式開發,也不分前端、後端程式員,大家都是全乾工程師。隨著前後端分離、移動端開發的興起,用後端渲染數據的開發方式效率低下,已經不能滿足業務對需求快速上線的要 ...
  • ★ JWT基本概念 JWT(JSON Web Token)是一種用於在網路應用之間傳遞信息的安全方式。它是一種基於 JSON 的開放標準(RFC 7519),用於在網路應用之間安全地傳輸聲明。JWT 通常用於身份驗證和授權,以及在分散式系統中傳遞聲明。 ★ JWT組成部分 JWT 由三部分組成:頭部 ...
  • 什麼是監視器(Monitor)? 在Java中,監視器(Monitor)是用來實現線程同步的一種機制。每個Java對象都有一個與之關聯的監視器,線程可以通過synchronized關鍵字來獲取和釋放對象的監視器。監視器的主要作用是確保在同一時刻只有一個線程可以執行同步塊或同步方法,從而實現線程的互斥 ...
  • ★ 背景說明 在Django REST framework (DRF) 前後端分離項目中,解決CSRF問題通常有以下幾種方法: 1. 禁用CSRF驗證,但這會降低安全性。(不推薦) 2. 使用csrftoken cookie 3. 在前端每次 POST、PUT 或 DELETE 請求前先發起一個GE ...
  • 數字簽名作為PDF文檔中的重要安全機制,不僅能夠驗證文件的來源,還能確保文件內容在傳輸過程中未被篡改。然而,如何正確驗證PDF文件的數字簽名,是確保文件完整性和可信度的關鍵。本文將詳細介紹如何使用免費.NET控制項通過C#驗證PDF簽名的有效性以及驗證PDF文檔是否被修改。 C# 驗證PDF數字簽名有 ...
  • 一、WTM是什麼 WalkingTec.Mvvm框架(簡稱WTM)最早開發與2013年,基於Asp.net MVC3 和 最早的Entity Framework, 當初主要是為瞭解決公司內部開發效率低,代碼風格不統一的問題。2017年9月,將代碼移植到了.Net Core上,併進行了深度優化和重構, ...
  • 實現了一個支持長短按得按鈕組件,單擊可以觸發Click事件,長按可以觸發LongPressed事件,長按鬆開時觸發LongClick事件。還可以和自定義外觀相結合,實現自定義的按鈕外形。 ...
  • WPF的按鈕提供了Template模板,可以通過修改Template模板中的內容對按鈕的樣式進行自定義。結合資源字典,可以將自定義資源在xaml視窗、自定義控制項或者整個App當中調用 ...
一周排行
    -Advertisement-
    Play Games
  • 通過WPF的按鈕、文本輸入框實現了一個簡單的SpinBox數字輸入用戶組件並可以通過數據綁定數值和步長。本文中介紹了通過Xaml代碼實現自定義組件的佈局,依賴屬性的定義和使用等知識點。 ...
  • 以前,我看到一個朋友在對一個系統做初始化的時候,通過一組魔幻般的按鍵,調出來一個隱藏的系統設置界面,這個界面在常規的菜單或者工具欄是看不到的,因為它是一個後臺設置的關鍵界面,不公開,同時避免常規用戶的誤操作,它是作為一個超級管理員的入口功能,這個是很不錯的思路。其實Winform做這樣的處理也是很容... ...
  • 一:背景 1. 講故事 前些天有位朋友找到我,說他的程式每次關閉時就會自動崩潰,一直找不到原因讓我幫忙看一下怎麼回事,這位朋友應該是第二次找我了,分析了下 dump 還是挺經典的,拿出來給大家分享一下吧。 二:WinDbg 分析 1. 為什麼會崩潰 找崩潰原因比較簡單,用 !analyze -v 命 ...
  • 在一些報表模塊中,需要我們根據用戶操作的名稱,來動態根據人員姓名,更新報表的簽名圖片,也就是電子手寫簽名效果,本篇隨筆介紹一下使用FastReport報表動態更新人員簽名圖片。 ...
  • 最新內容優先發佈於個人博客:小虎技術分享站,隨後逐步搬運到博客園。 創作不易,如果覺得有用請在Github上為博主點亮一顆小星星吧! 博主開始學習編程於11年前,年少時還只會使用cin 和cout ,給單片機點點燈。那時候,類似async/await 和future/promise 模型的認知還不是 ...
  • 之前在阿裡雲ECS 99元/年的活動實例上搭建了一個測試用的MINIO服務,以前都是直接當基礎設施來使用的,這次準備自己學一下S3相容API相關的對象存儲開發,因此有了這個小工具。目前僅包含上傳功能,後續計劃開發一個類似圖床的對象存儲應用。 ...
  • 目錄簡介快速入門安裝 NuGet 包實體類User資料庫類DbFactory增刪改查InsertSelectUpdateDelete總結 簡介 NPoco 是 PetaPoco 的一個分支,具有一些額外的功能,截至現在 github 星數 839。NPoco 中文資料沒多少,我是被博客園群友推薦的, ...
  • 前言 前面使用 Admin.Core 的代碼生成器生成了通用代碼生成器的基礎模塊 分組,模板,項目,項目模型,項目欄位的基礎功能,本篇繼續完善,實現最核心的模板生成功能,並提供生成預覽及代碼文件壓縮下載 準備 首先清楚幾個模塊的關係,如何使用,簡單畫一個流程圖 前面完成了基礎的模板組,模板管理,項目 ...
  • 假設需要實現一個圖標和文本結合的按鈕 ,普通做法是 直接重寫該按鈕的模板; 如果想作為通用的呢? 兩種做法: 附加屬性 自定義控制項 推薦使用附加屬性的形式 第一種:附加屬性 創建Button的附加屬性 ButtonExtensions 1 public static class ButtonExte ...
  • 在C#中,委托是一種引用類型的數據類型,允許我們封裝方法的引用。通過使用委托,我們可以將方法作為參數傳遞給其他方法,或者將多個方法組合在一起,從而實現更靈活的編程模式。委托類似於函數指針,但提供了類型安全和垃圾回收等現代語言特性。 基本概念 定義委托 定義委托需要指定它所代表的方法的原型,包括返回類 ...