網站首頁 編程語言 正文
WPF 實現多選下拉控件
框架使用.NET40
;
Visual Studio 2022
;
創建控件?MultiSelectComboBox
?繼承?ListBox
?。
- 依賴屬性?
IsSelectAllActive
?是否支持顯示全選,默認?false
?。 - 依賴屬性?
SelectAllContent
?全選控件的?Content
,默認顯示?全選
?。 - 依賴屬性?
Delimiter
?分隔符,默認顯示?;
?。 - 依賴屬性?
Text
?顯示選擇的所有?Item
?。 - 其他與
ComboBox
?依賴屬性一致。
實現代碼
1)?MultiSelectComboBox.xaml
?代碼如下:
using?System; using?System.ComponentModel; using?System.Linq; using?System.Windows; using?System.Windows.Controls; using?System.Windows.Controls.Primitives; using?System.Windows.Input; using?System.Windows.Threading; namespace?WPFDevelopers.Controls { ????public?class?MultiSelectComboBox?:?ListBox ????{ ????????private?const?string?PART_Popup?=?"PART_Popup"; ????????private?const?string?PART_CheckBoxAll?=?"PART_CheckBoxAll"; ????????public?static?readonly?DependencyProperty?IsDropDownOpenProperty?= ????????????DependencyProperty.Register("IsDropDownOpen",?typeof(bool),?typeof(MultiSelectComboBox), ????????????????new?PropertyMetadata(false)); ????????public?static?readonly?DependencyProperty?MaxDropDownHeightProperty ????????????=?DependencyProperty.Register("MaxDropDownHeight",?typeof(double),?typeof(MultiSelectComboBox), ????????????????new?PropertyMetadata(SystemParameters.PrimaryScreenHeight?/?3)); ????????public?static?readonly?DependencyProperty?SelectAllContentProperty?= ????????????DependencyProperty.Register("SelectAllContent",?typeof(object),?typeof(MultiSelectComboBox), ????????????????new?PropertyMetadata("全選")); ????????public?static?readonly?DependencyProperty?IsSelectAllActiveProperty?= ????????????DependencyProperty.Register("IsSelectAllActive",?typeof(bool),?typeof(MultiSelectComboBox), ????????????????new?PropertyMetadata(false)); ????????public?static?readonly?DependencyProperty?DelimiterProperty?= ????????????DependencyProperty.Register("Delimiter",?typeof(string),?typeof(MultiSelectComboBox), ????????????????new?PropertyMetadata(";")); ????????public?static?readonly?DependencyProperty?TextProperty?= ????????????DependencyProperty.Register("Text",?typeof(string),?typeof(MultiSelectComboBox), ????????????????new?PropertyMetadata(string.Empty,?OnTextChanged)); ????????private?bool?_ignoreTextValueChanged; ????????private?MultiSelectComboBoxItem?_multiSelectComboBoxItem; ????????private?Popup?_popup; ????????public?bool?IsDropDownOpen ????????{ ????????????get?=>?(bool)GetValue(IsDropDownOpenProperty); ????????????set?=>?SetValue(IsDropDownOpenProperty,?value); ????????} ????????[Bindable(true)] ????????[Category("Layout")] ????????[TypeConverter(typeof(LengthConverter))] ????????public?double?MaxDropDownHeight ????????{ ????????????get?=>?(double)GetValue(MaxDropDownHeightProperty); ????????????set?=>?SetValue(MaxDropDownHeightProperty,?value); ????????} ????????public?object?SelectAllContent ????????{ ????????????get?=>?GetValue(SelectAllContentProperty); ????????????set?=>?SetValue(SelectAllContentProperty,?value); ????????} ????????public?bool?IsSelectAllActive ????????{ ????????????get?=>?(bool)GetValue(IsSelectAllActiveProperty); ????????????set?=>?SetValue(IsSelectAllActiveProperty,?value); ????????} ????????public?string?Delimiter ????????{ ????????????get?=>?(string)GetValue(DelimiterProperty); ????????????set?=>?SetValue(DelimiterProperty,?value); ????????} ????????public?string?Text ????????{ ????????????get?=>?(string)GetValue(TextProperty); ????????????set?=>?SetValue(TextProperty,?value); ????????} ????????private?static?void?OnIsDropDownOpenChanged(DependencyObject?d,?DependencyPropertyChangedEventArgs?e) ????????{ ????????????var?MultiSelectComboBox?=?(MultiSelectComboBox)d; ????????????if?(!(bool)e.NewValue) ????????????????MultiSelectComboBox.Dispatcher.BeginInvoke(new?Action(()?=>?{?Mouse.Capture(null);?}), ????????????????????DispatcherPriority.Send); ????????} ????????private?static?void?OnTextChanged(DependencyObject?d,?DependencyPropertyChangedEventArgs?e) ????????{ ????????} ????????protected?override?bool?IsItemItsOwnContainerOverride(object?item) ????????{ ????????????return?item?is?MultiSelectComboBoxItem; ????????} ????????protected?override?DependencyObject?GetContainerForItemOverride() ????????{ ????????????return?new?MultiSelectComboBoxItem(); ????????} ????????protected?override?void?OnSelectionChanged(SelectionChangedEventArgs?e) ????????{ ????????????UpdateText(); ????????????base.OnSelectionChanged(e); ????????} ????????public?override?void?OnApplyTemplate() ????????{ ????????????base.OnApplyTemplate(); ????????????_popup?=?GetTemplateChild(PART_Popup)?as?Popup; ????????????_multiSelectComboBoxItem?=?GetTemplateChild(PART_CheckBoxAll)?as?MultiSelectComboBoxItem; ????????????_multiSelectComboBoxItem.Selected?+=?_MultiSelectComboBoxItem_Selected; ????????????_multiSelectComboBoxItem.Unselected?+=?_MultiSelectComboBoxItem_Unselected; ????????} ????????private?void?_MultiSelectComboBoxItem_Unselected(object?sender,?RoutedEventArgs?e) ????????{ ????????????if?(_ignoreTextValueChanged)?return; ????????????_ignoreTextValueChanged?=?true; ????????????UnselectAll(); ????????????_ignoreTextValueChanged?=?false; ????????????UpdateText(); ????????} ????????private?void?_MultiSelectComboBoxItem_Selected(object?sender,?RoutedEventArgs?e) ????????{ ????????????if?(_ignoreTextValueChanged)?return; ????????????_ignoreTextValueChanged?=?true; ????????????SelectAll(); ????????????_ignoreTextValueChanged?=?false; ????????????UpdateText(); ????????} ????????protected?virtual?void?UpdateText() ????????{ ????????????if?(_ignoreTextValueChanged)?return; ????????????var?newValue?=?string.Join(Delimiter,?SelectedItems.Cast<object>().Select(x?=>?GetItemDisplayValue(x))); ????????????if?(string.IsNullOrWhiteSpace(Text)?||?!Text.Equals(newValue)) ????????????{ ????????????????_ignoreTextValueChanged?=?true; ????????????????if?(_multiSelectComboBoxItem?!=?null) ????????????????????_multiSelectComboBoxItem.SetCurrentValue(IsSelectedProperty,?SelectedItems.Count?==?Items.Count); ????????????????SetCurrentValue(TextProperty,?newValue); ????????????????_ignoreTextValueChanged?=?false; ????????????} ???????????? ????????} ????????protected?object?GetItemDisplayValue(object?item) ????????{ ????????????if?(string.IsNullOrWhiteSpace(DisplayMemberPath)) ????????????{ ????????????????var?property?=?item.GetType().GetProperty("Content"); ????????????????if?(property?!=?null) ????????????????????return?property.GetValue(item,?null); ????????????} ????????????var?nameParts?=?DisplayMemberPath.Split('.'); ????????????if?(nameParts.Length?==?1) ????????????{ ????????????????var?property?=?item.GetType().GetProperty(DisplayMemberPath); ????????????????if?(property?!=?null) ????????????????????return?property.GetValue(item,?null); ????????????} ????????????return?item; ????????} ????} }
2)?MultiSelectComboBoxItem.cs
?代碼如下:
using?System.Windows.Controls; namespace?WPFDevelopers.Controls { ????public?class?MultiSelectComboBoxItem?:?ListBoxItem ????{ ????} }
3)?MultiSelectComboBox.xaml
?代碼如下:
<ResourceDictionary?xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" ????????????????????xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" ????????????????????xmlns:controls="clr-namespace:WPFDevelopers.Controls" ????????????????????xmlns:helpers="clr-namespace:WPFDevelopers.Helpers"> ???? ????<ResourceDictionary.MergedDictionaries> ????????<ResourceDictionary?Source="Basic/ControlBasic.xaml"/> ????</ResourceDictionary.MergedDictionaries> ??<BooleanToVisibilityConverter?x:Key="bool2VisibilityConverter"?/> ?<Style?x:Key="DefaultMultiSelectComboBoxItem"?TargetType="{x:Type?controls:MultiSelectComboBoxItem}"> ??<Setter?Property="HorizontalContentAlignment"?Value="{Binding?HorizontalContentAlignment,?RelativeSource={RelativeSource?AncestorType={x:Type?ItemsControl}}}"/> ??<Setter?Property="VerticalContentAlignment"?Value="{Binding?VerticalContentAlignment,?RelativeSource={RelativeSource?AncestorType={x:Type?ItemsControl}}}"/> ??<Setter?Property="SnapsToDevicePixels"?Value="True"/> ??<Setter?Property="Background"?Value="Transparent"/> ??<Setter?Property="BorderBrush"?Value="Transparent"/> ??<Setter?Property="Foreground"?Value="{DynamicResource?RegularTextSolidColorBrush}"/> ??<Setter?Property="BorderThickness"?Value="0"/> ??<Setter?Property="Height"?Value="34"?/> ??<Setter?Property="Margin"?Value="1,0"?/> ??<Setter?Property="Padding"?Value="6,0"/> ??<Setter?Property="Cursor"?Value="Hand"?/> ??<Setter?Property="Template"> ???<Setter.Value> ????<ControlTemplate?TargetType="{x:Type?controls:MultiSelectComboBoxItem}"> ?????<Border?x:Name="PART_Border" ???????BorderBrush="{TemplateBinding?BorderBrush}" ???????BorderThickness="{TemplateBinding?BorderThickness}" ???????Background="{TemplateBinding?Background}" ???????SnapsToDevicePixels="true" ???????Padding="{TemplateBinding?Padding}"> ??????<CheckBox?Foreground="{TemplateBinding?Foreground}" ??????????HorizontalAlignment="Stretch" ??????????VerticalAlignment="{TemplateBinding?VerticalContentAlignment}" ??????????MinHeight="{TemplateBinding?MinHeight}" ??????????Padding="{TemplateBinding?Padding}" ??????????IsChecked="{Binding?IsSelected,RelativeSource={RelativeSource?TemplatedParent},Mode=TwoWay}"> ???????<ContentPresenter?HorizontalAlignment="{TemplateBinding?HorizontalContentAlignment}" ??????????VerticalAlignment="{TemplateBinding?VerticalContentAlignment}" ??????????x:Name="PART_ContentPresenter" ??????????SnapsToDevicePixels="{TemplateBinding?SnapsToDevicePixels}" ??????????TextElement.Foreground="{TemplateBinding?Foreground}"/> ??????</CheckBox> ?????</Border> ?????<ControlTemplate.Triggers> ??????<Trigger?Property="IsMouseOver"?Value="True"> ???????<Setter?Property="Background"?Value="{DynamicResource?DefaultBackgroundSolidColorBrush}"/> ??????</Trigger> ?????</ControlTemplate.Triggers> ????</ControlTemplate> ???</Setter.Value> ??</Setter> ?</Style> ?<Style?TargetType="{x:Type?controls:MultiSelectComboBox}"> ??<Setter?Property="ScrollViewer.HorizontalScrollBarVisibility"?Value="Auto"?/> ??<Setter?Property="ScrollViewer.VerticalScrollBarVisibility"?Value="Auto"?/> ??<Setter?Property="ScrollViewer.CanContentScroll"?Value="True"?/> ??<Setter?Property="SelectionMode"?Value="Multiple"/> ??<Setter?Property="MinWidth"?Value="120"?/> ??<Setter?Property="MinHeight"?Value="{StaticResource?MinHeight}"?/> ????????<Setter?Property="Height"?Value="{StaticResource?MinHeight}"?/> ??<Setter?Property="ItemContainerStyle"?Value="{StaticResource?DefaultMultiSelectComboBoxItem}"/> ??<Setter?Property="HorizontalContentAlignment"?Value="Left"?/> ??<Setter?Property="VerticalContentAlignment"?Value="Center"?/> ????????<Setter?Property="BorderBrush"?Value="{DynamicResource?BaseSolidColorBrush}"/> ????????<Setter?Property="BorderThickness"?Value="1"/> ??<Setter?Property="Background"?Value="{DynamicResource?BackgroundSolidColorBrush}"/> ??<Setter?Property="Padding"?Value="14.5,3,30,3"/> ??<Setter?Property="Template"> ???<Setter.Value> ????????????????<ControlTemplate?TargetType="{x:Type?controls:MultiSelectComboBox}"> ?????<ControlTemplate.Resources> ??????<Storyboard?x:Key="OpenStoryboard"> ???????<DoubleAnimation?Storyboard.TargetName="PART_DropDown" ?????????????Storyboard.TargetProperty="(Grid.RenderTransform).(ScaleTransform.ScaleY)" ?????????????To="1"?Duration="00:00:.2" ?????????????EasingFunction="{StaticResource?ExponentialEaseOut}"/> ??????</Storyboard> ??????<Storyboard?x:Key="CloseStoryboard"> ???????<DoubleAnimation?Storyboard.TargetName="PART_DropDown" ?????????????Storyboard.TargetProperty="(Grid.RenderTransform).(ScaleTransform.ScaleY)" ?????????????To="0"?Duration="00:00:.2" ?????????????EasingFunction="{StaticResource?ExponentialEaseOut}"/> ??????</Storyboard> ?????</ControlTemplate.Resources> ????????????????????<controls:SmallPanel?SnapsToDevicePixels="True"> ??????<Border?Name="PART_Border" ????????Background="{TemplateBinding?Background}" ????????BorderBrush="{TemplateBinding?BorderBrush}" ????????BorderThickness="{TemplateBinding?BorderThickness}" ????????SnapsToDevicePixels="True" ????????CornerRadius="{Binding?Path=(helpers:ElementHelper.CornerRadius),?RelativeSource={RelativeSource?TemplatedParent}}"?/> ??????<ToggleButton?x:Name="PART_ToggleButton" ???????????Template="{StaticResource?ComboBoxToggleButton}" ???????????Style="{x:Null}" ???????????Focusable="False" ???????????ClickMode="Release" ???????????IsChecked="{Binding?IsDropDownOpen,?Mode=TwoWay,?RelativeSource={RelativeSource?TemplatedParent}}"/> ??????<TextBox?Name="PART_EditableTextBox" ?????????Template="{StaticResource?ComboBoxTextBox}" ?????????HorizontalAlignment="{TemplateBinding?HorizontalContentAlignment}" ?????????VerticalAlignment="{TemplateBinding?VerticalContentAlignment}" ?????????Margin="{TemplateBinding?Padding}" ?????????Focusable="True" ?????????Text="{Binding?Text,RelativeSource={RelativeSource?TemplatedParent},Mode=TwoWay}" ?????????Background="{TemplateBinding?Background}" ?????????SelectionBrush="{DynamicResource?WindowBorderBrushSolidColorBrush}" ?????????IsReadOnly="True"?Style="{x:Null}"?/> ?????? ??????<Popup?x:Name="PART_Popup" ????????AllowsTransparency="True" ????????PlacementTarget="{Binding?ElementName=PART_ToggleButton}" ????????IsOpen="{Binding?IsDropDownOpen,RelativeSource={RelativeSource?TemplatedParent},Mode=TwoWay}" ????????Placement="Bottom"?StaysOpen="False"> ????????????????????????????<controls:SmallPanel?x:Name="PART_DropDown" ??????????MinWidth="{TemplateBinding?FrameworkElement.ActualWidth}" ????????Margin="24,2,24,24" ????????MaxHeight="{TemplateBinding?MaxDropDownHeight}" ????????RenderTransformOrigin=".5,0" ????????SnapsToDevicePixels="True"> ????????????????????????????????<controls:SmallPanel.RenderTransform> ?????????<ScaleTransform?ScaleY="0"/> ????????</controls:SmallPanel.RenderTransform> ????????<Border ?????????Name="PART_DropDownBorder" ?????????Background="{TemplateBinding?Background}" ?????????BorderBrush="{TemplateBinding?BorderBrush}" ?????????BorderThickness="{TemplateBinding?BorderThickness}" ?????????SnapsToDevicePixels="True" ?????????????????????????????????CornerRadius="{Binding?Path=(helpers:ElementHelper.CornerRadius),RelativeSource={RelativeSource?TemplatedParent}}" ?????????UseLayoutRounding="True" ?????????Effect="{StaticResource?PopupShadowDepth}"/> ????????<Grid?ClipToBounds="False" ???????????Margin="0,8"?> ?????????<Grid.RowDefinitions> ??????????<RowDefinition?Height="Auto"/> ??????????<RowDefinition/> ?????????</Grid.RowDefinitions> ?????????<controls:MultiSelectComboBoxItem?x:Name="PART_CheckBoxAll" ????????????????????Visibility="{TemplateBinding?IsSelectAllActive,Converter={StaticResource?bool2VisibilityConverter}}" ????????????????????Style="{TemplateBinding?ItemContainerStyle}" ????????????????????Content="{TemplateBinding?SelectAllContent}"/> ?????????<ScrollViewer?x:Name="DropDownScrollViewer"?Grid.Row="1" ???????????????ScrollViewer.VerticalScrollBarVisibility="Auto"> ??????????<ItemsPresenter?x:Name="ItemsPresenter" ???????????????KeyboardNavigation.DirectionalNavigation="Contained" ???????????????SnapsToDevicePixels="{TemplateBinding?SnapsToDevicePixels}"/> ?????????</ScrollViewer> ????????</Grid> ???????</controls:SmallPanel> ??????</Popup> ?????</controls:SmallPanel> ?????<ControlTemplate.Triggers> ??????<Trigger?SourceName="PART_ToggleButton"?Property="IsChecked"?Value="True"> ???????<Trigger.EnterActions> ????????<BeginStoryboard?x:Name="BeginStoryboardOpenStoryboard"?Storyboard="{StaticResource?OpenStoryboard}"?/> ???????</Trigger.EnterActions> ???????<Trigger.ExitActions> ????????<StopStoryboard?BeginStoryboardName="BeginStoryboardOpenStoryboard"?/> ???????</Trigger.ExitActions> ??????</Trigger> ??????<Trigger?SourceName="PART_ToggleButton"?Property="IsChecked"?Value="False"> ???????<Trigger.EnterActions> ????????<BeginStoryboard?x:Name="BeginStoryboardCloseStoryboard"?Storyboard="{StaticResource?CloseStoryboard}"?/> ???????</Trigger.EnterActions> ???????<Trigger.ExitActions> ????????<StopStoryboard?BeginStoryboardName="BeginStoryboardCloseStoryboard"?/> ???????</Trigger.ExitActions> ??????</Trigger> ??????<Trigger?Property="IsMouseOver"?Value="True"> ????????????????????????????<Setter?Property="BorderBrush"?TargetName="PART_Border"?Value="{DynamicResource?PrimaryNormalSolidColorBrush}"/> ??????</Trigger> ??????<Trigger?SourceName="PART_Popup"?Property="AllowsTransparency"?Value="True"> ???????<Setter?TargetName="PART_DropDownBorder"??Property="Margin"?Value="0,2,0,0"?/> ??????</Trigger> ?????</ControlTemplate.Triggers> ????</ControlTemplate> ???</Setter.Value> ??</Setter> ?</Style> </ResourceDictionary>
4)?MultiSelectComboBoxExample.xaml
?代碼如下:
<UserControl?x:Class="WPFDevelopers.Samples.ExampleViews.MultiSelectComboBoxExample" ?????????????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:WPFDevelopers.Samples.ExampleViews" ?????????????xmlns:wpfdev="https://github.com/WPFDevelopersOrg/WPFDevelopers" ?????????????xmlns:controls="clr-namespace:WPFDevelopers.Samples.Controls" ?????????????xmlns:model="clr-namespace:WPFDevelopers.Sample.Models" ?????????????mc:Ignorable="d"? ?????????????d:DesignHeight="450"?d:DesignWidth="800"> ????<UserControl.Resources> ????????<model:HospitalList?x:Key="myHospitalList"/> ????</UserControl.Resources> ????<controls:CodeViewer> ????????<UniformGrid?Columns="2"> ????????????<wpfdev:MultiSelectComboBox ????????????????VerticalContentAlignment="Center"? ????????????????HorizontalAlignment="Center" ????????????????Delimiter="^"?Width="200"> ????????????????<wpfdev:MultiSelectComboBoxItem>Option?1</wpfdev:MultiSelectComboBoxItem> ????????????????<wpfdev:MultiSelectComboBoxItem>Option?2</wpfdev:MultiSelectComboBoxItem> ????????????????<wpfdev:MultiSelectComboBoxItem>Option?3</wpfdev:MultiSelectComboBoxItem> ????????????????<wpfdev:MultiSelectComboBoxItem>Option?4</wpfdev:MultiSelectComboBoxItem> ????????????????<wpfdev:MultiSelectComboBoxItem>Option?5</wpfdev:MultiSelectComboBoxItem> ????????????</wpfdev:MultiSelectComboBox> ????????????<wpfdev:MultiSelectComboBox?VerticalContentAlignment="Center"? ?????????????????????????????????????????HorizontalAlignment="Center" ?????????????????????????????????????????IsSelectAllActive="True" ?????????????????????????????ItemsSource="{Binding?Source={StaticResource?myHospitalList}}" ?????????????????????????????DisplayMemberPath="DoctorName" ?????????????????????????????SelectedValuePath="ID"?Width="200"> ????????????</wpfdev:MultiSelectComboBox> ????????</UniformGrid> ????????<controls:CodeViewer.SourceCodes> ????????????<controls:SourceCodeModel? ????????????????CodeSource="/WPFDevelopers.SamplesCode;component/ExampleViews/MultiSelectComboBoxExample.xaml"? ????????????????CodeType="Xaml"/> ????????????<controls:SourceCodeModel? ????????????????CodeSource="/WPFDevelopers.SamplesCode;component/ExampleViews/MultiSelectComboBoxExample.xaml.cs"? ????????????????CodeType="CSharp"/> ????????</controls:CodeViewer.SourceCodes> ????</controls:CodeViewer> </UserControl>
效果圖
原文鏈接:https://mp.weixin.qq.com/s/uHloylkBzIbuxEiC5KEyBA
相關推薦
- 2022-03-29 關于Android冷啟動耗時優化詳解_Android
- 2022-05-11 spring cloud alibaba nacos搭建最小可運行微服務
- 2022-08-16 C/C++函數的調用約定的使用_C 語言
- 2022-11-02 Python中turtle庫常用代碼匯總_python
- 2023-04-08 Swift?HTTP加載請求Loading?Requests教程_Swift
- 2022-11-24 詳解python中@classmethod和@staticmethod方法_python
- 2022-08-03 C#記一次http協議multipart/form-data的boundary問題_C#教程
- 2022-10-04 Android實現圓圈倒計時_Android
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支