基于WPF實(shí)現(xiàn)Message消息提醒控件
WPF 實(shí)現(xiàn) Message 消息提醒控件
- 框架使用
.NET4 至 .NET6
; Visual Studio 2022
;- 接著上一篇
實(shí)現(xiàn)代碼
1)新增 MessageListBoxItem.cs
代碼如下:
新增了名為MessageType
的依賴屬性,類型為MessageBoxImage
,默認(rèn)值為MessageBoxImage.Information
新增了名為IsCenter
的依賴屬性,默認(rèn)值為false
,為true
則內(nèi)容居中顯示。
using?System.Windows; using?System.Windows.Controls; namespace?WPFDevelopers.Controls { ????public?class?MessageListBoxItem?:?ListBoxItem ????{ ????????public?MessageBoxImage?MessageType ????????{ ????????????get?{?return?(MessageBoxImage)GetValue(MessageTypeProperty);?} ????????????set?{?SetValue(MessageTypeProperty,?value);?} ????????} ????????public?static?readonly?DependencyProperty?MessageTypeProperty?= ????????????DependencyProperty.Register("MessageType",?typeof(MessageBoxImage),?typeof(MessageListBoxItem),?new?PropertyMetadata(MessageBoxImage.Information)); ????????public?bool?IsCenter ????????{ ????????????get?{?return?(bool)GetValue(IsCenterProperty);?} ????????????set?{?SetValue(IsCenterProperty,?value);?} ????????} ????????public?static?readonly?DependencyProperty?IsCenterProperty?= ????????????DependencyProperty.Register("IsCenter",?typeof(bool),?typeof(MessageListBoxItem),?new?PropertyMetadata(false)); ????} }
2)新增 MessageListBox.cs
代碼如下:
自定義MessageListBox
繼承ListBox
,其中重寫了兩個(gè)方法:IsItemItsOwnContainerOverride
和GetContainerForItemOverride
。
GetContainerForItemOverride
方法用于創(chuàng)建并返回一個(gè)新的容器對(duì)象,用于承載列表框中的項(xiàng)。在這里,它創(chuàng)建并返回一個(gè)MessageListBoxItem
的實(shí)例作為容器對(duì)象。
IsItemItsOwnContainerOverride
方法用于確定給定的項(xiàng)是否應(yīng)該作為其自己的容器。在這里,它檢查傳入的item
對(duì)象是否是MessageListBoxItem
的實(shí)例。如果是,則返回true
,表示該項(xiàng)是其自己的容器;否則,返回false
。
using?System.Windows; using?System.Windows.Controls; namespace?WPFDevelopers.Controls { ????public?class?MessageListBox?:?ListBox ????{ ????????protected?override?bool?IsItemItsOwnContainerOverride(object?item) ????????{ ????????????return?item?is?MessageListBoxItem; ????????} ????????protected?override?DependencyObject?GetContainerForItemOverride() ????????{ ????????????return?new?MessageListBoxItem(); ????????} ????} }
3)新增 MessageAdorner.cs
代碼如下:
MessageAdorner
是一個(gè)繼承自Adorner
的自定義類。它用于在裝飾元素上顯示消息的附加裝飾器。
構(gòu)造函數(shù)MessageAdorner(UIElement adornedElement)
接受一個(gè)UIElement
類型的參數(shù),作為要進(jìn)行裝飾的元素。
Push
方法用于將消息添加到裝飾器中。它接受消息內(nèi)容、消息類型和是否居中顯示的參數(shù)。如果裝飾器尚未創(chuàng)建,則會(huì)創(chuàng)建一個(gè)MessageListBox
并將其設(shè)置為裝飾器的子元素。然后,根據(jù)傳入的參數(shù)創(chuàng)建一個(gè)新的MessageListBoxItem
,并將其插入到列表框的頂部。
Child
屬性用于獲取或設(shè)置裝飾器的子元素。當(dāng)設(shè)置子元素時(shí),會(huì)將子元素添加到裝飾器的可視化子元素集合中;當(dāng)子元素為null
時(shí),會(huì)從可視化子元素集合中移除子元素。
VisualChildrenCount
屬性返回裝飾器的可視化子元素?cái)?shù)量。
ArrangeOverride
方法用于調(diào)整裝飾器的布局。在這里,根據(jù)裝飾元素的寬度和子元素的期望大小,計(jì)算出子元素的水平位置,并將其排列在裝飾器的頂部。
GetVisualChild
方法用于獲取指定索引處的可視化子元素。在這里,如果索引為0且子元素不為null
,則返回子元素;否則,調(diào)用基類的方法返回對(duì)應(yīng)索引的可視化子元素。
using?System.Windows; using?System.Windows.Documents; using?System.Windows.Media; namespace?WPFDevelopers.Controls { ????public?class?MessageAdorner?:?Adorner ????{ ????????private?MessageListBox?listBox; ????????private?UIElement?_child; ????????private?FrameworkElement?adornedElement; ????????public?MessageAdorner(UIElement?adornedElement)?:?base(adornedElement) ????????{ ????????????this.adornedElement?=?adornedElement?as?FrameworkElement; ????????} ????????public?void?Push(string?message,?MessageBoxImage?type?=?MessageBoxImage.Information,?bool?center?=?false) ????????{ ????????????if?(listBox?==?null) ????????????{ ????????????????listBox?=?new?MessageListBox(); ????????????????Child?=?listBox; ????????????} ????????????var?mItem?=?new?MessageListBoxItem?{?Content?=?message,?MessageType?=?type,?IsCenter?=?center?}; ????????????listBox.Items.Insert(0,?mItem); ????????} ????????public?UIElement?Child ????????{ ????????????get?=>?_child; ????????????set ????????????{ ????????????????if?(value?==?null) ????????????????{ ????????????????????RemoveVisualChild(_child); ????????????????????_child?=?value; ????????????????????return; ????????????????} ????????????????AddVisualChild(value); ????????????????_child?=?value; ????????????} ????????} ????????protected?override?int?VisualChildrenCount ????????{ ????????????get ????????????{ ????????????????return?_child?!=?null???1?:?0; ????????????} ????????} ????????protected?override?Size?ArrangeOverride(Size?finalSize) ????????{ ????????????var?x?=?(adornedElement.ActualWidth?-?_child.DesiredSize.Width)?/?2; ????????????_child.Arrange(new?Rect(new?Point(x,?0),?_child.DesiredSize)); ????????????return?finalSize; ????????} ????????protected?override?Visual?GetVisualChild(int?index) ????????{ ????????????if?(index?==?0?&&?_child?!=?null)?return?_child; ????????????return?base.GetVisualChild(index); ????????} ????} }
4)新增 Message.cs
代碼如下:
CreateMessageAdorner
方法用于創(chuàng)建消息裝飾器MessageAdorner
。它接受一些參數(shù),如窗口所有者Window owner
、消息內(nèi)容string message
、消息類型MessageBoxImage type
和是否居中顯示bool center
。在方法內(nèi)部,它首先檢查是否已經(jīng)存在消息裝飾器實(shí)例messageAdorner
,如果存在,則調(diào)用裝飾器的Push
方法將新的消息添加到裝飾器中,并直接返回。如果不存在消息裝飾器實(shí)例,則根據(jù)提供的窗口所有者或獲取默認(rèn)窗口ControlsHelper.GetDefaultWindow()
,然后獲取對(duì)應(yīng)的裝飾層AdornerLayer
。如果裝飾層為空,則拋出異常。接著,創(chuàng)建一個(gè)新的消息裝飾器實(shí)例,并將其添加到裝飾層中。最后,調(diào)用裝飾器的Push
方法將消息添加到裝飾器中。
Push
方法是一個(gè)擴(kuò)展方法,用于在指定的窗口上顯示消息。它接受窗口對(duì)象Window owner
作為第一個(gè)參數(shù),以及其他參數(shù),如消息內(nèi)容string message
、消息類型MessageBoxImage type
和是否居中顯示bool center
。在方法內(nèi)部,它調(diào)用CreateMessageAdorner
方法,并傳遞相應(yīng)的參數(shù)。
另一個(gè)重載的Push
方法是直接在靜態(tài)上下文中調(diào)用的。它接受消息內(nèi)容string message
、消息類型MessageBoxImage type
和是否居中顯示bool center
作為參數(shù),并調(diào)用CreateMessageAdorner
方法。
using?System; using?System.Linq; using?System.Windows; using?WPFDevelopers.Helpers; namespace?WPFDevelopers.Controls { ????public?static?class?Message ????{ ????????private?static?MessageAdorner?messageAdorner; ????????static?void?CreateMessageAdorner(Window?owner?=?null,?string?message?=?null,?MessageBoxImage?type?=?MessageBoxImage.Information,?bool?center?=?false) ????????{ ????????????try ????????????{ ????????????????if?(messageAdorner?!=?null) ????????????????{ ????????????????????messageAdorner.Push(message,?type,?center); ????????????????????return; ????????????????} ????????????????if?(owner?==?null) ????????????????????owner?=?ControlsHelper.GetDefaultWindow(); ????????????????var?layer?=?ControlsHelper.GetAdornerLayer(owner); ????????????????if?(layer?==?null) ????????????????????throw?new?Exception("not?AdornerLayer?is?null"); ????????????????messageAdorner?=?new?MessageAdorner(layer); ????????????????layer.Add(messageAdorner); ????????????????messageAdorner.Push(message,?type,?center); ????????????} ????????????catch?(Exception) ????????????{ ????????????????throw; ????????????} ????????} ????????public?static?void?Push(this?Window?owner,?string?message,?MessageBoxImage?type?=?MessageBoxImage.Information,?bool?center?=?false) ????????{ ????????????CreateMessageAdorner(owner,?message,?type,?center); ????????} ????????public?static?void?Push(string?message,?MessageBoxImage?type?=?MessageBoxImage.Information,?bool?center?=?false) ????????{ ????????????CreateMessageAdorner(message:?message,?type:?type,?center:?center); ????????} ????} }
5)新增 MessageListBoxItem.xaml
代碼如下:
XAML
代碼定義一個(gè)名為Storyboard_Loaded
的故事板(Storyboard
),其中包含了四個(gè)DoubleAnimation
動(dòng)畫
- 第一個(gè)
DoubleAnimation
動(dòng)畫將目標(biāo)元素PART_SmallPanel
的Y
軸縮放屬性ScaleTransform.ScaleY
從0
變化到1
,持續(xù)時(shí)間為0.2
秒。這會(huì)使PART_SmallPanel
在加載時(shí)以漸變的方式顯示出來(lái)。 - 第二個(gè)
DoubleAnimation
動(dòng)畫將目標(biāo)元素PART_SmallPanel
的不透明度屬性Opacity
從0.1
變化到1
,持續(xù)時(shí)間為0.2
秒。這也是為了使PART_SmallPanel
在加載時(shí)以漸變的方式顯示出來(lái)。 - 第三個(gè)
DoubleAnimation
動(dòng)畫將目標(biāo)元素PART_SmallPanel
的Y
軸縮放屬性ScaleTransform.ScaleY
從1
變化到0
,持續(xù)時(shí)間為0.2
秒。這個(gè)動(dòng)畫在10
秒后開始執(zhí)行,會(huì)使PART_SmallPanel
以漸變的方式從可見(jiàn)狀態(tài)變?yōu)椴豢梢?jiàn)狀態(tài)。 - 第四個(gè)
DoubleAnimation
動(dòng)畫將目標(biāo)元素PART_SmallPanel
的不透明度屬性Opacity
從1
變化到0
,持續(xù)時(shí)間為0.2
秒。同樣地,在10秒后開始執(zhí)行,使PART_SmallPanel
以漸變的方式從可見(jiàn)狀態(tài)變?yōu)椴豢梢?jiàn)狀態(tài)。
定義一個(gè)名為Storyboard_Close
的故事板Storyboard
,其中包含了兩個(gè)DoubleAnimation
動(dòng)畫。
- 第一個(gè)
DoubleAnimation
動(dòng)畫將目標(biāo)元素PART_SmallPanel
的Y軸縮放屬性(UIElement.RenderTransform).(ScaleTransform.ScaleY)
從1
變化到0
,持續(xù)時(shí)間為0.2
秒。這會(huì)使PART_SmallPanel
以漸變的方式從可見(jiàn)狀態(tài)變?yōu)椴豢梢?jiàn)狀態(tài)。 - 第二個(gè)
DoubleAnimation
動(dòng)畫將目標(biāo)元素PART_SmallPanel
的不透明度屬性(Opacity
)從1
變化到0,持續(xù)時(shí)間為0
秒。該動(dòng)畫在0.2
秒后開始執(zhí)行,使PART_SmallPanel
以立即消失的方式從可見(jiàn)狀態(tài)變?yōu)椴豢梢?jiàn)狀態(tài)。
?<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> ????<Style ????????x:Key="WD.MessageListBoxItem" ????????BasedOn="{StaticResource?WD.ControlBasicStyle}" ????????TargetType="{x:Type?controls:MessageListBoxItem}"> ????????<Setter?Property="FontSize"?Value="{DynamicResource?WD.NormalFontSize}"?/> ????????<Setter?Property="Foreground"?Value="{DynamicResource?WD.RegularTextSolidColorBrush}"?/> ????????<Setter?Property="Background"?Value="{DynamicResource?WD.BackgroundSolidColorBrush}"?/> ????????<Setter?Property="helpers:ListBoxItemExtensions.AutoRemoveOnOpacityZero"?Value="True"?/> ????????<Setter?Property="Width"?Value="300"?/> ????????<Setter?Property="Height"?Value="Auto"?/> ????????<Setter?Property="Padding"?Value="10"?/> ????????<Setter?Property="Margin"?Value="4,2"?/> ????????<Setter?Property="Template"> ????????????<Setter.Value> ????????????????<ControlTemplate?TargetType="{x:Type?controls:MessageListBoxItem}"> ????????????????????<ControlTemplate.Resources> ????????????????????????<Storyboard?x:Key="Storyboard_Close"> ????????????????????????????<DoubleAnimation ????????????????????????????????Storyboard.TargetName="PART_SmallPanel" ????????????????????????????????Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleY)" ????????????????????????????????From="1" ????????????????????????????????To="0" ????????????????????????????????Duration="0:0:0.2"?/> ????????????????????????????<DoubleAnimation ????????????????????????????????BeginTime="0:0:0.2" ????????????????????????????????Storyboard.TargetProperty="Opacity" ????????????????????????????????From="1" ????????????????????????????????To="0" ????????????????????????????????Duration="0:0:0"?/> ????????????????????????</Storyboard> ????????????????????????<Storyboard?x:Key="Storyboard_Loaded"> ????????????????????????????<DoubleAnimation ????????????????????????????????Storyboard.TargetName="PART_SmallPanel" ????????????????????????????????Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleY)" ????????????????????????????????From="0" ????????????????????????????????To="1" ????????????????????????????????Duration="0:0:0.2"?/> ????????????????????????????<DoubleAnimation ????????????????????????????????Storyboard.TargetName="PART_SmallPanel" ????????????????????????????????Storyboard.TargetProperty="Opacity" ????????????????????????????????From=".1" ????????????????????????????????To="1" ????????????????????????????????Duration="0:0:0.2"?/> ????????????????????????????<DoubleAnimation ????????????????????????????????BeginTime="0:0:10" ????????????????????????????????Storyboard.TargetName="PART_SmallPanel" ????????????????????????????????Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleY)" ????????????????????????????????From="1" ????????????????????????????????To="0" ????????????????????????????????Duration="0:0:0.2"?/> ????????????????????????????<DoubleAnimation ????????????????????????????????BeginTime="0:0:10" ????????????????????????????????Storyboard.TargetProperty="Opacity" ????????????????????????????????From="1" ????????????????????????????????To="0" ????????????????????????????????Duration="0:0:0.2"?/> ????????????????????????</Storyboard> ????????????????????</ControlTemplate.Resources> ????????????????????<controls:SmallPanel ????????????????????????x:Name="PART_SmallPanel" ????????????????????????Margin="{TemplateBinding?Margin}" ????????????????????????RenderTransformOrigin=".5,0"> ????????????????????????<controls:SmallPanel.RenderTransform> ????????????????????????????<ScaleTransform?/> ????????????????????????</controls:SmallPanel.RenderTransform> ????????????????????????<Border ????????????????????????????x:Name="PART_Border" ????????????????????????????Background="{TemplateBinding?Background}" ????????????????????????????BorderBrush="{TemplateBinding?BorderBrush}" ????????????????????????????BorderThickness="{TemplateBinding?BorderThickness}" ????????????????????????????CornerRadius="{Binding?Path=(helpers:ElementHelper.CornerRadius),?RelativeSource={RelativeSource?TemplatedParent}}" ????????????????????????????Effect="{StaticResource?WD.NormalShadowDepth}" ????????????????????????????SnapsToDevicePixels="True" ????????????????????????????UseLayoutRounding="True"?/> ????????????????????????<Border?Padding="{TemplateBinding?Padding}"> ????????????????????????????<Grid> ????????????????????????????????<Grid.ColumnDefinitions> ????????????????????????????????????<ColumnDefinition?Width="*"?/> ????????????????????????????????????<ColumnDefinition?Width="Auto"?/> ????????????????????????????????</Grid.ColumnDefinitions> ????????????????????????????????<DockPanel?x:Name="PART_DockPanel"?Grid.Column="0"> ????????????????????????????????????<Path ????????????????????????????????????????x:Name="PART_Path" ????????????????????????????????????????Width="15" ????????????????????????????????????????Height="15" ????????????????????????????????????????Data="{StaticResource?WD.InformationGeometry}" ????????????????????????????????????????Fill="{DynamicResource?WD.PrimaryNormalSolidColorBrush}" ????????????????????????????????????????Stretch="Fill"?/> ????????????????????????????????????<TextBlock ????????????????????????????????????????Grid.Column="1" ????????????????????????????????????????Margin="5,0,0,0" ????????????????????????????????????????VerticalAlignment="Center" ????????????????????????????????????????FontSize="{TemplateBinding?FontSize}" ????????????????????????????????????????Foreground="{TemplateBinding?Foreground}" ????????????????????????????????????????Text="{TemplateBinding?Content}" ????????????????????????????????????????TextWrapping="Wrap"?/> ????????????????????????????????</DockPanel> ????????????????????????????????<Button ????????????????????????????????????x:Name="PART_CloseButton" ????????????????????????????????????Grid.Column="2" ????????????????????????????????????Width="30" ????????????????????????????????????Height="28" ????????????????????????????????????Padding="0" ????????????????????????????????????HorizontalAlignment="Right" ????????????????????????????????????Style="{StaticResource?WD.PathButton}"> ????????????????????????????????????<Path ????????????????????????????????????????Width="10" ????????????????????????????????????????Height="10" ????????????????????????????????????????HorizontalAlignment="Center" ????????????????????????????????????????VerticalAlignment="Center" ????????????????????????????????????????Data="{DynamicResource?WD.WindowCloseGeometry}" ????????????????????????????????????????Fill="{DynamicResource?WD.SecondaryTextSolidColorBrush}" ????????????????????????????????????????Stretch="Fill"?/> ????????????????????????????????</Button> ????????????????????????????</Grid> ????????????????????????</Border> ????????????????????</controls:SmallPanel> ????????????????????<ControlTemplate.Triggers> ????????????????????????<Trigger?Property="MessageType"?Value="Warning"> ????????????????????????????<Setter?TargetName="PART_Path"?Property="Data"?Value="{StaticResource?WD.WarningGeometry}"?/> ????????????????????????????<Setter?TargetName="PART_Path"?Property="Fill"?Value="{StaticResource?WD.WarningSolidColorBrush}"?/> ????????????????????????????<Setter?Property="Foreground"?Value="{StaticResource?WD.WarningSolidColorBrush}"?/> ????????????????????????</Trigger> ????????????????????????<Trigger?Property="MessageType"?Value="Error"> ????????????????????????????<Setter?TargetName="PART_Path"?Property="Data"?Value="{StaticResource?WD.ErrorGeometry}"?/> ????????????????????????????<Setter?TargetName="PART_Path"?Property="Fill"?Value="{StaticResource?WD.DangerSolidColorBrush}"?/> ????????????????????????????<Setter?Property="Foreground"?Value="{StaticResource?WD.DangerSolidColorBrush}"?/> ????????????????????????</Trigger> ????????????????????????<Trigger?Property="MessageType"?Value="Information"> ????????????????????????????<Setter?TargetName="PART_Path"?Property="Data"?Value="{StaticResource?WD.InformationGeometry}"?/> ????????????????????????????<Setter?TargetName="PART_Path"?Property="Fill"?Value="{StaticResource?WD.SuccessSolidColorBrush}"?/> ????????????????????????????<Setter?Property="Foreground"?Value="{StaticResource?WD.SuccessSolidColorBrush}"?/> ????????????????????????</Trigger> ????????????????????????<Trigger?Property="MessageType"?Value="Question"> ????????????????????????????<Setter?TargetName="PART_Path"?Property="Data"?Value="{StaticResource?WD.QuestionGeometry}"?/> ????????????????????????????<Setter?TargetName="PART_Path"?Property="Fill"?Value="{StaticResource?WD.NormalSolidColorBrush}"?/> ????????????????????????????<Setter?Property="Foreground"?Value="{StaticResource?WD.NormalSolidColorBrush}"?/> ????????????????????????</Trigger> ????????????????????????<Trigger?Property="IsCenter"?Value="True"> ????????????????????????????<Setter?TargetName="PART_DockPanel"?Property="HorizontalAlignment"?Value="Center"?/> ????????????????????????</Trigger> ????????????????????????<EventTrigger?RoutedEvent="Button.Click"?SourceName="PART_CloseButton"> ????????????????????????????<BeginStoryboard?x:Name="BeginStoryboardClose"?Storyboard="{StaticResource?Storyboard_Close}"?/> ????????????????????????</EventTrigger> ????????????????????????<EventTrigger?RoutedEvent="Loaded"> ????????????????????????????<BeginStoryboard?x:Name="BeginStoryboardLoaded"?Storyboard="{StaticResource?Storyboard_Loaded}"?/> ????????????????????????</EventTrigger> ????????????????????????<EventTrigger?RoutedEvent="Unloaded"> ????????????????????????????<StopStoryboard?BeginStoryboardName="BeginStoryboardLoaded"?/> ????????????????????????????<StopStoryboard?BeginStoryboardName="BeginStoryboardClose"?/> ????????????????????????</EventTrigger> ????????????????????????<Trigger?Property="Opacity"?Value="0"> ????????????????????????????<Setter?Property="Visibility"?Value="Collapsed"?/> ????????????????????????</Trigger> ????????????????????</ControlTemplate.Triggers> ????????????????</ControlTemplate> ????????????</Setter.Value> ????????</Setter> ????</Style> ????<Style?x:Key="WD.MessageListBox"?TargetType="{x:Type?controls:MessageListBox}"> ????????<Setter?Property="BorderThickness"?Value="0"?/> ????????<Setter?Property="Background"?Value="Transparent"?/> ????????<Setter?Property="ScrollViewer.VerticalScrollBarVisibility"?Value="Hidden"?/> ????</Style> ????<Style?BasedOn="{StaticResource?WD.MessageListBoxItem}"?TargetType="{x:Type?controls:MessageListBoxItem}"?/> ????<Style?BasedOn="{StaticResource?WD.MessageListBox}"?TargetType="{x:Type?controls:MessageListBox}"?/> </ResourceDictionary>
6)新增 ListBoxItemExtensions
代碼如下:
在方法內(nèi)部,首先將sender
轉(zhuǎn)換為ListBoxItem
類型,并進(jìn)行空引用檢查。然后,創(chuàng)建一個(gè)綁定對(duì)象binding
,將其源設(shè)置為當(dāng)前的item
,并將綁定模式設(shè)置為單向。
接下來(lái),使用DependencyPropertyDescriptor
從UIElement.OpacityProperty
屬性獲取一個(gè)依賴屬性描述符dpd
。通過(guò)調(diào)用AddValueChanged
方法,將一個(gè)值更改事件的處理程序添加到item
上。當(dāng)item
的不透明度Opacity
小于0.1時(shí),該處理程序?qū)?zhí)行以下操作:
- 獲取父級(jí)
ItemsControl
,即包含item
的列表框。 - 如果找到了父級(jí)
ItemsControl
,則使用ItemContainerGenerator
從item
獲取關(guān)聯(lián)的數(shù)據(jù)項(xiàng)(selectedItem
)。 - 從父級(jí)
ItemsControl
的Items
集合中移除selectedItem
。 - 調(diào)用父級(jí)
ItemsControl
的Refresh
方法,以刷新列表框的顯示。
using?System.ComponentModel; using?System.Windows; using?System.Windows.Controls; using?System.Windows.Data; namespace?WPFDevelopers.Helpers { ????public?static?class?ListBoxItemExtensions ????{ ????????public?static?readonly?DependencyProperty?AutoRemoveOnOpacityZeroProperty?= ????????DependencyProperty.RegisterAttached("AutoRemoveOnOpacityZero",?typeof(bool),?typeof(ListBoxItemExtensions),?new?PropertyMetadata(false,?OnAutoRemoveOnOpacityZeroChanged)); ????????public?static?bool?GetAutoRemoveOnOpacityZero(DependencyObject?obj) ????????{ ????????????return?(bool)obj.GetValue(AutoRemoveOnOpacityZeroProperty); ????????} ????????public?static?void?SetAutoRemoveOnOpacityZero(DependencyObject?obj,?bool?value) ????????{ ????????????obj.SetValue(AutoRemoveOnOpacityZeroProperty,?value); ????????} ????????private?static?void?OnAutoRemoveOnOpacityZeroChanged(DependencyObject?obj,?DependencyPropertyChangedEventArgs?e) ????????{ ????????????ListBoxItem?item?=?obj?as?ListBoxItem; ????????????if?(item?!=?null) ????????????{ ????????????????if?((bool)e.NewValue) ????????????????????item.Loaded?+=?Item_Loaded; ????????????????else ????????????????????item.Loaded?-=?Item_Loaded; ????????????} ????????} ????????private?static?void?Item_Loaded(object?sender,?RoutedEventArgs?e) ????????{ ????????????var?item?=?sender?as?ListBoxItem; ????????????if?(item?!=?null) ????????????{ ????????????????var?binding?=?new?Binding("Opacity"); ????????????????binding.Source?=?item; ????????????????binding.Mode?=?BindingMode.OneWay; ????????????????var?dpd?=?DependencyPropertyDescriptor.FromProperty(UIElement.OpacityProperty,?typeof(UIElement)); ????????????????dpd.AddValueChanged(item,?(s,?args)?=> ????????????????{ ????????????????????if?(item.Opacity?<?0.1) ????????????????????{ ????????????????????????var?parent?=?ItemsControl.ItemsControlFromItemContainer(item); ????????????????????????if?(parent?!=?null) ????????????????????????{ ????????????????????????????object?selectedItem?=?parent.ItemContainerGenerator.ItemFromContainer(item); ????????????????????????????parent.Items.Remove(selectedItem); ????????????????????????????parent.Items.Refresh(); ????????????????????????} ????????????????????} ????????????????}); ????????????} ????????} ????} }
7)新增 示例 代碼如下:
<wd:Window ????x:Class="MessageSample.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:local="clr-namespace:MessageSample" ????xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" ????xmlns:wd="https://github.com/WPFDevelopersOrg/WPFDevelopers" ????Title="WPFDevelopers?-?Message" ????Width="800" ????Height="450" ????mc:Ignorable="d"> ????<Grid> ????????<StackPanel ????????????Grid.Row="1" ????????????HorizontalAlignment="Center" ????????????VerticalAlignment="Bottom" ????????????Orientation="Horizontal"> ????????????<Button ????????????????Click="AddButton_Click" ????????????????Content="Info?Message" ????????????????Style="{StaticResource?WD.SuccessPrimaryButton}" ????????????????Tag="Info"?/> ????????????<Button ????????????????Click="AddButton_Click" ????????????????Content="Error?Message" ????????????????Style="{StaticResource?WD.DangerPrimaryButton}" ????????????????Tag="Error"?/> ????????????<Button ????????????????Click="AddButton_Click" ????????????????Content="Warning?Message" ????????????????Style="{StaticResource?WD.WarningPrimaryButton}" ????????????????Tag="Warning"?/> ????????????<Button ????????????????Click="AddButton_Click" ????????????????Content="Question?Message" ????????????????Style="{StaticResource?WD.PrimaryButton}" ????????????????Tag="Question"?/> ????????????<Button ????????????????Click="AddButton_Click" ????????????????Content="Long?Message" ????????????????Style="{StaticResource?WD.SuccessPrimaryButton}" ????????????????Tag="Long"?/> ????????</StackPanel> ????</Grid> </wd:Window>
8) 示例 代碼如下:
private?void?AddButton_Click(object?sender,?RoutedEventArgs?e) ????????{ ????????????var?btn?=?sender?as?Button; ????????????switch?(btn.Tag) ????????????{ ????????????????case?"Info": ????????????????????Message.Push(App.Current.MainWindow,?"This?is?a?info?message",?MessageBoxImage.Information); ????????????????????break; ????????????????case?"Error": ????????????????????Message.Push("This?is?a?error?message",?MessageBoxImage.Error,?true); ????????????????????break; ????????????????case?"Warning": ????????????????????Message.Push("This?is?a?warning?message",?MessageBoxImage.Warning,?true); ????????????????????break; ????????????????case?"Question": ????????????????????Message.Push("This?is?a?question?message",?MessageBoxImage.Question); ????????????????????break; ????????????????default: ????????????????????Message.Push("這是一條很長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)長(zhǎng)消息",?MessageBoxImage.Information); ????????????????????break; ????????????} ????????}
效果圖
以上就是基于WPF實(shí)現(xiàn)Message消息提醒控件的詳細(xì)內(nèi)容,更多關(guān)于WPF Message消息提醒的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
使用C#9中records作為強(qiáng)類型ID的實(shí)例教程
這篇文章主要給大家介紹了關(guān)于使用C#9中records作為強(qiáng)類型ID的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01Linq兩個(gè)List集合取交集的實(shí)現(xiàn)
這篇文章主要介紹了Linq兩個(gè)List集合取交集的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12C#和JavaScript實(shí)現(xiàn)交互的方法
最近做一個(gè)小項(xiàng)目不可避免的需要前端腳本與后臺(tái)進(jìn)行交互。由于是在asp.net中實(shí)現(xiàn),故問(wèn)題演化成asp.net中jiavascript與后臺(tái)c#如何進(jìn)行交互。2015-05-05WinForm IP地址輸入框控件實(shí)現(xiàn)
這篇文章主要為大家詳細(xì)介紹了WinForm IP地址輸入框控件的實(shí)現(xiàn)代碼,基于VS2010模擬windows系統(tǒng)自帶IP輸入框,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-05-05C#正則匹配RegexOptions選項(xiàng)的組合使用方法
本文主要簡(jiǎn)單介紹RegexOptions各種選項(xiàng)的作用,并介紹如何組合使用,為初學(xué)者解除一些疑惑。2016-04-04C#中XmlTextWriter讀寫xml文件詳細(xì)介紹
.NET中包含了很多支持XML的類,這些類使得程序員使用XML編程就如同理解XML文件一樣簡(jiǎn)單。在這篇文章中,我將給出這樣的一個(gè)類的使用示例,這個(gè)類就是XmlTextWriter類2013-04-04unity實(shí)現(xiàn)延遲回調(diào)工具
這篇文章主要為大家詳細(xì)介紹了unity實(shí)現(xiàn)延遲回調(diào)工具,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09C#實(shí)現(xiàn)過(guò)濾sql特殊字符的方法集合
這篇文章主要介紹了C#實(shí)現(xiàn)過(guò)濾sql特殊字符的方法,以實(shí)例形式分析總結(jié)了C#針對(duì)SQL危險(xiǎn)字符的幾種常用的過(guò)濾技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-11-11C#實(shí)現(xiàn)定時(shí)關(guān)機(jī)小應(yīng)用
這篇文章主要為大家詳細(xì)介紹了C#實(shí)現(xiàn)定時(shí)關(guān)機(jī)小應(yīng)用,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-07-07