【WPF】Command 的一些使用方案

来源:https://www.cnblogs.com/tcjiaan/p/18327235
-Advertisement-
Play Games

Command,即命令,具體而言,指的是實現了 ICommand 介面的對象。此介面要求實現者包含這些成員: 1、CanExecute 方法:確定該命令是否可以執行,若可,返回 true;若不可,返回 false; 2、CanExecuteChanged 事件:發送命令(命令源)的控制項可以訂閱此事件 ...


Command,即命令,具體而言,指的是實現了 ICommand 介面的對象。此介面要求實現者包含這些成員:

1、CanExecute 方法:確定該命令是否可以執行,若可,返回 true;若不可,返回 false;

2、CanExecuteChanged 事件:發送命令(命令源)的控制項可以訂閱此事件,當命令的可執行性改變時能得到通知;

3、Execute 方法:執行命令時調用此方法。可以將命令邏輯寫在此方法中。

命令源(ICommandSource)

發送命令的控制項就是命令源,例如常見的菜單項、按鈕等。即命令是怎麼觸發的,這肯定與用戶交互有關的。無交互功能的控制項一般不需要發送命令。有命令源就會有命令目標,若命令源是發送者,那麼命令目標就是命令的接收者(命令最終作用在誰身上)。比如,單擊 K 按鈕後清空 T 控制項中的文本。則,K是命令源,T就是命令目標。這樣舉例相信大伙伴們能夠理解,老周就不說太多,理論部分越簡單越好懂。這裡沒什麼玄的,只要你分清角色就行,誰發出,誰接收。

命令必須有觸發者,所以,源是必須的,並且,作為命令源的控制項要實現 ICommandSource 介面,並實現三個成員:

1、Command: 要發送的命令對象;

2、CommandParameter:命令參數。這個是任意對象,由你自己決定它是啥,比如,你的命令是刪除某位員工的數據記錄,那麼,這個參數可能是員工ID。這個參數是可選的,當你的命令邏輯需要額外數據時才用到,不用預設為 null 就行了;

3、CommandTarget:目標。命令要作用在哪個控制項上。其實這個也是可選的,命令可以無目標控制項。比如,刪除個員工記錄,如果知道要刪除哪記錄,那這裡不需要目標控制項。當然,如果你的邏輯是要清空文本框的文本,那目標控制項是 TextBox。這個取決你的代碼邏輯。

像 Button、MenuItem 這些控制項,就是命令源,都實現 ICommandSource 介面。

命令邏輯

命令邏輯就是你的命令要乾的活。咱們做個演示。

下麵示例將通過命令來刪除一條學生記錄。Student 類的定義如下:

    public class Student
    {
        public string? Name { get; set; } = string.Empty;
        public int ID { get; set; }
        public int Age { get; set; }
        public string Major { get; set; } = string.Empty;
    }

    public class StudentViewManager
    {
        private static readonly ObservableCollection<Student> _students = new ObservableCollection<Student>();

        static StudentViewManager()
        {
            _students.Add(new Student()
            {
                ID = 1,
                Name = "小陳",
                Age = 20,
                Major = "打老虎專業"
            });
            _students.Add(new Student()
            {
                ID = 2,
                Name = "小張",
                Age = 21,
                Major = "鋪地磚專業"
            });
            _students.Add(new Student()
            {
                ID = 3,
                Name = "呂布",
                Age = 23,
                Major = "坑義父專業戶"
            });
        }

        public static ObservableCollection<Student> Students
        {
            get { return _students; }
        }
    }

 然後,定義一個實現 ICommand 介面的類。

    public class DelStuCommand : ICommand
    {
        public event EventHandler? CanExecuteChanged;

        public bool CanExecute(object? parameter)
        {
            return !(StudentViewManager.Students.Count == 0);
        }

        public void Execute(object? parameter)
        {
            Student? s = parameter as Student;
            if (s == null)
                return;

            StudentViewManager.Students.Remove(s);
        }
    }

執行此命令需要參數,好讓它知道要刪除哪條學生記錄。

下麵 XAML 中,ListBox 控制項顯示學生列表,按鈕引用上述命令對象。

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition Height="auto"/>
        </Grid.RowDefinitions>
        <Grid.Resources>
            <local:DelStuCommand x:Key="cmd"/>
        </Grid.Resources>
        <Button Content="刪除" Grid.Row="1" Command="{StaticResource cmd}"
                CommandParameter="{Binding ElementName=tc, Path=SelectedItem}"/>
        <ListBox x:Name="tc" Grid.Row="0">
            <ItemsControl.ItemTemplate>
                <DataTemplate DataType="local:Student">
                    <TextBlock>
                        <Run Text="{Binding Name}"/>
                        <Span> | </Span>
                        <Run Text="{Binding Major}" Foreground="Blue"/>
                    </TextBlock>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ListBox>               
    </Grid>

Button 類實現了 ICommandSource 介面,通過 CommandParameter 屬性指定要傳遞給命令的參數。

運行程式後,在 ListBox 中選擇一項,然後點“刪除”按鈕。

刪除後,只剩下兩項。重覆以下操作,當所有記錄都刪除後,“刪除”按鈕就會被禁用。

從這個示例可以瞭解到,命令可以把某種行為封裝為一個單獨的整體。這樣能增加其可復用性,按鈕、菜單、工具欄按鈕都可以使用同一個命令,實現相同的功能。

路由命令與 CommandBinding

實現 ICommand 介面雖然簡單易用,但它也有一個問題:如果我的程式里有很多命令邏輯,那我就要定義很多命令類。比如像這樣的,你豈不是要定義幾十個命令類。

這樣就引出 RoutedCommand 類的用途了。

RoutedCommand 類實現了 ICommand 介面,它封裝了一些通用邏輯,具體邏輯將以事件的方式處理。RoutedCommand 類的事件均來自 CommandManager 類所註冊的路由(隧道)事件。即

1、CanExecute 和 PreviewCanExecute 事件:當要確定命令是否能夠執行時會發生該事件。Preview 開頭的表示隧道事件。可能有大伙伴不太記得這個名詞。其實,路由事件和隧道事件本質一樣,只是傳遞的方向不同。挖隧道的時候是不是從外頭往裡面鑽?所以,隧道事件就是從外層元素往裡面傳播;路由事件就相反,從裡向外傳播。

2、Executed 和 PreviewExecuted 事件:咱們可以處理這事件,然後將自己要實現的命令邏輯寫上即可。

可見,有了 RoutedCommand,咱們就不需要定義一堆命令類了,而是全用它,代碼邏輯在 Executed 事件中寫。這裡也包括 RoutedUICommand  命令,這個類只不過多了個 Text 屬性,用來指定關聯的文本罷了,文本會顯示在菜單上。

不過,咱們在使用時不會直接去處理 RoutedCommand 類的事件,而是配合另一個類—— CommandBinding 來使用。有了它,事件才能冒泡(或下沉),也就是可向上或向下傳播。傳播的路徑是從目標對象(Command Target)開始,到最後能捕捉到事件的 CommandBindings 結束。這個不理解不重要,後面咱們用例子說明。

 

下麵咱們再做一個示例。這個例子中,咱們用四個菜單項來改變矩形的顏色。

由於現在用的是 RoutedCommand 類,我們不需要定義命令類了,所以能在 XAML 文檔中直接把命令聲明在資源中。

    <Window.Resources>
        <!--命令列表-->
        <RoutedCommand x:Key="greenCmd" />
        <RoutedCommand x:Key="silverCmd" />
        <RoutedCommand x:Key="redCmd" />
        <RoutedCommand x:Key="blackCmd" />
    </Window.Resources>

我們定義一組菜單,以及一個矩形。

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="auto"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Menu>
            <MenuItem Header="顏色">
                <MenuItem Header="綠色" Command="{StaticResource greenCmd}" CommandTarget="{Binding ElementName=rect}"/>
                <MenuItem Header="銀色" Command="{StaticResource silverCmd}" CommandTarget="{Binding ElementName=rect}"/>
                <MenuItem Header="紅色" Command="{StaticResource redCmd}" CommandTarget="{Binding ElementName=rect}"/>
                <MenuItem Header="黑色" Command="{StaticResource blackCmd}" CommandTarget="{Binding ElementName=rect}"/>
            </MenuItem>
        </Menu>
        <Rectangle Grid.Row="1" Height="80" Width="100" Name="rect" Fill="Blue" />
    </Grid>

網格分兩行,上面是菜單,下麵是矩形。每個菜單項的 Command 屬性已經引用了所需的命令對象。CommandTarget 屬性通過綁定引用矩形對象。這裡要註意,Target 要求的是實現 IInputElement 介面的類型。可見,不是所有對象都能充當目標的。Rectangle 類可以作為命令目標。

這時不要直接處理 RoutedCommand 類的事件,而是要藉助 CommandBinding。UIElement 的子類都繼承 CommandBindings 集合,所以放心用,大部分界面元素都可以用。本例中,我們在 Grid 上寫 CommandBinding。

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="auto"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Grid.CommandBindings>
            <CommandBinding Command="{StaticResource greenCmd}" 
                                CanExecute="OnRectCanExecut"
                                Executed="OnGreenCmdExe"/>
            <CommandBinding Command="{StaticResource silverCmd}"
                                CanExecute="OnRectCanExecut"
                                Executed="OnSilverCmdExe"/>
            <CommandBinding Command="{StaticResource redCmd}"
                                CanExecute="OnRectCanExecut"
                                Executed="OnRedCmdExe"/>
            <CommandBinding Command="{StaticResource blackCmd}"
                                CanExecute="OnRectCanExecut"
                                Executed="OnBlackCmdExe" />
        </Grid.CommandBindings>
        <Menu>
            ……
            </MenuItem>
        </Menu>
        <Rectangle Grid.Row="1" Height="80" Width="100" Name="rect" Fill="Blue" />
    </Grid>

在使用 CommandBinding 時,註意 Command 所引用的命令時你要用的,這裡就是要和四個菜單項所引用的命令一致,不然,CanExecute 和 Executed 事件不起作用(命令不能正確觸發)。如果事件邏輯相同,可以共用一個 handler,比如上面的,CanExecute 事件就共用一個處理方法。

接下來,我們處理一下這些事件。

private void OnGreenCmdExe(object sender, ExecutedRoutedEventArgs e)
{
    Rectangle rect = (Rectangle)e.OriginalSource;
    rect.Fill = new SolidColorBrush(Colors.Green);
}

private void OnSilverCmdExe(object sender, ExecutedRoutedEventArgs e)
{
    Rectangle rect = (Rectangle)e.OriginalSource;
    rect.Fill = new SolidColorBrush(Colors.Silver);
}

private void OnRedCmdExe(object sender, ExecutedRoutedEventArgs e)
{
    Rectangle rect = (Rectangle)e.OriginalSource;
    rect.Fill = new SolidColorBrush(Colors.Red);
}

private void OnBlackCmdExe(object sender, ExecutedRoutedEventArgs e)
{
    Rectangle rect = (Rectangle)e.OriginalSource;
    rect.Fill = new SolidColorBrush(Colors.Black);
}

private void OnRectCanExecut(object sender, CanExecuteRoutedEventArgs e)
{
    e.CanExecute = (e.OriginalSource != null && e.OriginalSource is Rectangle);
}

在 OnRectCanExecut 方法,本例的判斷方式是只要命令目標不為空,並且是矩形對象,就允許執行命令。e.CanExecute 屬性就是用來設置一個布爾值,以表示能不能執行命令。

代碼很簡單,老周不多解釋了。重點說的是,引發這些事件的源頭是 Command Target。即 OriginalSource 引用的就是 Rectangle。事件路徑是從目標對象開始向上冒泡的——說人話就是從 Rectangle 開始向上找 CommandBinding,不管是哪個層次上的 CommandBinding,只要事件和命令是匹配的,就會觸發。

我們不妨這樣改,把 Grid 下的後兩個 CommandBinding 向上移,移到 Window 對象下。

    <Window.CommandBindings>
        <CommandBinding Command="{StaticResource redCmd}"
                                CanExecute="OnRectCanExecut"
                                Executed="OnRedCmdExe"/>
        <CommandBinding Command="{StaticResource blackCmd}"
                                CanExecute="OnRectCanExecut"
                                Executed="OnBlackCmdExe" />
    </Window.CommandBindings>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="auto"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Grid.CommandBindings>
            <CommandBinding Command="{StaticResource greenCmd}" 
                                CanExecute="OnRectCanExecut"
                                Executed="OnGreenCmdExe"/>
            <CommandBinding Command="{StaticResource silverCmd}"
                                CanExecute="OnRectCanExecut"
                                Executed="OnSilverCmdExe"/>
        </Grid.CommandBindings>
        <Menu>
            ……
        </Menu>
        ……
    </Grid>

運行後,你會發現,四個菜單都能用。

從 Rectangle 開始向上冒泡,先是在 Grid 元素上找到兩個 CommandBinding,匹配,用之;再往上,在 Window 元素上又找到兩個,匹配,用之。所以,最後就是四個都能用。因此,路由是以 Rectangle 為起點向上冒泡,直到 Window 對象。

其實,上面幾個 Executed 事件也可以合併到一個方法中處理,只要用 CommandParameter 區分哪種顏色就行。

 private void OnCmdExecuted(object sender, ExecutedRoutedEventArgs e)
 {
     Rectangle rect = (Rectangle)e.OriginalSource;
     // 獲取參數值
     int val = Convert.ToInt32(e.Parameter);
     // 根據參數選擇顏色
     SolidColorBrush brush = new();
     switch (val)
     {
         case 0:
             brush.Color = Colors.Green;
             break;
         case 1:
             brush.Color = Colors.Silver;
             break;
         case 2:
             brush.Color = Colors.Red;
             break;
         case 3:
             brush.Color = Colors.Black;
             break;
         default:
             brush.Color = Colors.Blue;
             break;
     }
     rect.Fill = brush;
 }

在 XAML 文檔中,替換前面設置的事件 handler,併在菜單項中設置 CommandParameter。

<CommandBinding Command="{StaticResource redCmd}"
                        CanExecute="OnRectCanExecut"
                        Executed="OnCmdExecuted"/>
<CommandBinding Command="{StaticResource blackCmd}"
                        CanExecute="OnRectCanExecut"
                        Executed="OnCmdExecuted" />
<CommandBinding Command="{StaticResource greenCmd}" 
                    CanExecute="OnRectCanExecut"
                    Executed="OnCmdExecuted"/>
<CommandBinding Command="{StaticResource silverCmd}"
                    CanExecute="OnRectCanExecut"
                    Executed="OnCmdExecuted"/>
<MenuItem Header="綠色" Command="{StaticResource greenCmd}" CommandTarget="{Binding ElementName=rect}" CommandParameter="0"/>
<MenuItem Header="銀色" Command="{StaticResource silverCmd}" CommandTarget="{Binding ElementName=rect}" CommandParameter="1"/>
<MenuItem Header="紅色" Command="{StaticResource redCmd}" CommandTarget="{Binding ElementName=rect}" CommandParameter="2"/>
<MenuItem Header="黑色" Command="{StaticResource blackCmd}" CommandTarget="{Binding ElementName=rect}" CommandParameter="3"/>

指定快捷按鍵

命令的好處不只是可以多個源共用代碼邏輯,還支持快捷鍵綁定。這就要用到 InputBinding 對象了,仔細看,發現這個類實現了 ICommandSource 介面。

public class InputBinding : System.Windows.Freezable, System.Windows.Input.ICommandSource

因此,它也可以與命令關聯,只要 InputBinding 被觸發,關聯的命令也會執行。下麵咱們為上面的示例添加快捷鍵。

<Window.InputBindings>
    <KeyBinding Gesture="ctrl+shift+1" 
                    Command="{StaticResource greenCmd}"
                    CommandTarget="{Binding ElementName=rect}"
                    CommandParameter="0"/>
    <KeyBinding Gesture="ctrl+shift+2"
                    Command="{StaticResource silverCmd}"
                    CommandTarget="{Binding ElementName=rect}"
                    CommandParameter="1"/>
    <KeyBinding Gesture="ctrl+shift+3"
                    Command="{StaticResource redCmd}"
                    CommandTarget="{Binding ElementName=rect}"
                    CommandParameter="2"/>
    <KeyBinding Gesture="CTRL+SHIFT+4"
                    Command="{StaticResource blackCmd}"
                    CommandTarget="{Binding ElementName=rect}"
                    CommandParameter="3"/>
</Window.InputBindings>

UIElement 類的派生類都繼承了 InputBindings 集合,通常我們是把 InputBinding 放到視窗的集合中。實際上這裡可以把 InputBinding 寫在 Grid.InputBindings 中。前面咱們提過,事件是從 Target 對象向上冒泡的,所以在視窗上定義 InputBinding 或 CommandBinding,可以儘可能地捕捉到命令事件。

InputBinding 只是基類,它有兩個派生類—— KeyBinding,MouseBinding。不用老周解釋,看名識類,你都猜到它們是幹嗎用的了。示例中用到的是快捷鍵,所以用 KeyBinding。快捷鍵在 XAML 中有兩種聲明方法:

1、如本例所示,直接設置 Gesture 屬性。使用按鍵的字元串形式,不分大小寫,按鍵之間用“+”連接,如 Ctrl + C。這種方法把修改鍵和普通鍵一起定義,方便好用;

2、修改鍵和按鍵分開定義。即使用 Key 和 Modifiers 屬性,Key 指定普通鍵,如“G”;Modifiers 指定修改鍵,如 "Ctrl + Alt"。因此,本示例的快捷鍵也可以這樣定義:

<KeyBinding Modifiers="Ctrl+Shift"
            Key="D4"
                Command="{StaticResource blackCmd}"
                CommandTarget="{Binding ElementName=rect}"
                CommandParameter="3"/>

這裡的 Key 屬性比較特別,不能直接寫“4”,因為無法從字元串“4”轉換為 Key 枚舉,會報錯,可以指定為“D4”、“D5”等。這裡所指定的數字鍵是大鍵盤區域的數字(QWERTYUIOP 上面那排),不是右邊小鍵盤的數字鍵。小鍵盤要用"NumPad4"。小數字鍵盤跟有些修改鍵組合後無效,經老周測試,Shift、Alt、Win這些鍵都無效,Ctrl 可以。所以,還是用字母鍵靠譜些,也不用區分大小鍵盤區域。

重點:Key + Modifiers 方式與 Gesture 方式只能二選一,不能同時使用,會產生歧義

CommandTarget 為什麼是可選的

前面提到,命令目標是可選的,可以不指定,為什麼呢?這就要看命令源的處理方式了。我們可以看看 WPF 內部的處理。

internal static bool CanExecuteCommandSource(ICommandSource commandSource)
{
    ICommand command = commandSource.Command;
    if (command != null)
    {
        object parameter = commandSource.CommandParameter;
        IInputElement target = commandSource.CommandTarget;

        RoutedCommand routed = command as RoutedCommand;
        if (routed != null)
        {
            if (target == null)
            {
                target = commandSource as IInputElement;
            }
            return routed.CanExecute(parameter, target);
        }
        else
        {
            return command.CanExecute(parameter);
        }
    }

    return false;
}

如果命令是 RoutedCommand,且目標是存在的,就觸發 CanExe 事件;如果未指定目標,則將命令源作為目標。

如果命令不是 RoutedCommand,則直接無視目標。

所以,總的來說,Target 就是可選的。不過,對於非路由的命令,預設會把鍵盤焦點所在的控制項視為目標。

現在,老周相信大伙伴們都會使用命令了。在實際使用中,你還可以把命令直接封裝進 Model 類型中,比如作為一個公共屬性。MVVM不是很喜歡這樣用的嗎?這樣封裝確實很方便的,尤其是你有N個視窗,這些視窗可能都出現一個“編輯員工信息”的菜單或按鈕。如果你的員工信息模型中直接封裝了命令,在命令的邏輯中打開編輯對話框。這樣就省了許多重覆代碼了,而且這 N 個視窗的代碼也變得簡潔了,你甚至都不用給按鈕們處理 Click 事件。

----------------------------------------------------------------------------------------------------------------------------------------------

最後,解釋一下老周最近寫水文為什麼效率這麼低。因為老周最近很光榮,經朋友介紹,以 A 公司員工的名義,被派遣到 B 集團總部的開發部門。就類似於外包之類了吧,就是過去那裡乾一段時間。這關係很複雜吧。其實老周本來是不想去的,但還是給朋友 45% 的面子(唉,人最可悲的就是總覺得面子可以當飯吃),就答應了,順便賺點生活費。包吃不包住,來回就用網約車。因為這“一段時間”太模糊,租房子不好弄,交押金什麼的,時間又不確定,咋整。所以,只好打車,費用找他們公司報銷。

如果你常被外派的話,可能知道這活是不好乾的。你想想,人家為什麼要找你上門?就是因為他們自己解決不了問題,你過去就是負責啃硬骨頭的。由於簽了保密協議,老周不能說是什麼項目。總之項目很大,TM的複雜,主要幫他們做優化。他們的辦公室跟菜市場似的,每天很熱鬧,上班可以走來走去,聊天扯蛋。氛圍不錯,你到處逛領導也不管,反正你得完成進度。老周粗略估算,一張桌子坐 8 個人,辦公室很大,有6列17行,能坐 6*17*8 個人,整棟樓有 2313 人(聽見他們廣播中是這樣說的),不知道算不算我們外包人員。想想他們的開發團隊有多大了。

畢竟是大集團公司,在東南亞和歐洲有很多個生產基地。所以他們的開發團隊本來設立是為子公司的工廠開發軟體系統的。不過,在食堂聽內部人員說,這幾年他們除了自己集團內

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

-Advertisement-
Play Games
更多相關文章
  • 寫在前面 昨天說了一下Java中的數據類型、運算符、選擇語句、迴圈語句部分的基礎知識,今天寫的編程題就是來檢驗這部分的成果,來看看你能寫出來幾題。答案也是僅供參考,如果有更好的解法歡迎在下麵留言! 題目展示 1.輸入自己的名字,年齡和性別,分別用不同的變數接收,並將輸入的信息做輸出。 代碼: pub ...
  • 在氣象學和環境科學的研究中,理解和預測氣象數據的周期性變化至關重要。小波分析作為一種高效的數學工具,近年來在氣象數據的周期性分析中得到了廣泛應用。本文將詳細介紹如何通過Python進行小波分析,以探究氣象數據中的周期性變化。 ...
  • 不管你是做數據分析,還是網路爬蟲,Web 開發、亦或是機器學習,你都離不開要和資料庫打交道,而 MySQL 又是最流行的一種資料庫,這篇文章介紹 Python 操作 MySQL 的5種方式,你可以在實際開發過程中根據實際情況合理選擇。 1、MySQLdb MySQLdb又叫MySQL-python ...
  • Java 的多線程是一種允許在一個程式中同時運行多個線程的技術。每個線程是獨立的執行路徑,可以併發執行,從而提高程式的效率和響應能力。 1. 線程基礎 Java 中的線程可以通過繼承 Thread 類或實現 Runnable 介面來創建和管理。 1.1 繼承 Thread 類 class MyThr ...
  • 背景:之前的項目做讀寫分離的時候用的 MybatisPlus的動態數據做的,很多地方使用的@DS直接指定的讀庫或者寫庫實現的業務;隨著表數據量越來越大,現在打算把比較大的表進行水平拆分,準備使用 ShardingJDBC實現,但是發現兩者配合起來並不是那麼順利,網上大部分文章都是直接把整個Shard ...
  • 一, 創建工程,引入依賴 @目錄一, 創建工程,引入依賴創建工程工程間的關係的建立配置各個工程當中的 pow 配置信息,相關的依賴父工程(也就是總項目工程)的 pow 配置demo-module06-generate 模塊中pow 配置: Mybatis 逆向工程的 pow 配置demo-modul ...
  • 流程式控制制語句結構 目錄流程式控制制語句結構1.順序結構定義與特點示例2.分支結構2.1. if-else語句2.2. switch語句3.迴圈結構1. for迴圈2. while迴圈3. do-while迴圈使用場景和註意事項4.跳轉語句5.繪製程式流程圖基本步驟常用符號示例工具 1.順序結構 定義與特 ...
  • 多線程編程是每一個開發必知必會的技能,在實際項目中,為了避免頻繁創建和銷毀線程,我們通常使用池化的思想,用線程池進行多線程開發。 線程池在開發中使用頻率非常高,也包含不少知識點,是一個高頻面試題,本篇總結線程池的使用經驗和需要註意的問題,更好的應對日常開發和麵試。 如有更多知識點,歡迎補充~ 異常處 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...