WPF自定義控件與樣式(11)-等待/忙/正在加載狀態(tài)-控件實(shí)現(xiàn)一.前言 申明:WPF自定義控件與樣式是一個(gè)系列文章,前后是有些關(guān)聯(lián)的,但大多是按照由簡(jiǎn)到繁的順序逐步發(fā)布的等,若有不明白的地方可以參考本系列前面的文章,文末附有部分文章鏈接,。 本文主要有三種實(shí)現(xiàn)方式:
二.簡(jiǎn)單忙碌狀態(tài)控件BusyBox 效果圖:
通過屬性"IsActive"控制控件是否啟用,后臺(tái)C#代碼: /// <summary> /// BusyBox.xaml 的交互邏輯 /// </summary> public partial class BusyBox : UserControl { public static readonly DependencyProperty IsActiveProperty = DependencyProperty.Register("IsActive", typeof(bool), typeof(BusyBox), new PropertyMetadata(false)); /// <summary> /// 是否啟用 /// </summary> public bool IsActive { get { return (bool)GetValue(IsActiveProperty); } set { SetValue(IsActiveProperty, value); } } static BusyBox() { DefaultStyleKeyProperty.OverrideMetadata(typeof(BusyBox), new FrameworkPropertyMetadata(typeof(BusyBox))); } } 使用了一個(gè)字體圖標(biāo),,觸發(fā)器中實(shí)現(xiàn)動(dòng)畫顯示的控制,,樣式代碼: <Style TargetType="{x:Type local:BusyBox}"> <Setter Property="Foreground" Value="{StaticResource TextForeground}"></Setter> <Setter Property="Width" Value="32"></Setter> <Setter Property="Height" Value="32"></Setter> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type local:BusyBox}"> <Grid VerticalAlignment="Center" HorizontalAlignment="Center" > <Viewbox Stretch="Uniform" VerticalAlignment="Center" HorizontalAlignment="Center"> <TextBlock Text="" x:Name="FIcon" FontSize="36" Style="{StaticResource FIcon}" RenderTransformOrigin="0.5,0.5" Foreground="{TemplateBinding Foreground}"> <TextBlock.RenderTransform> <RotateTransform x:Name="TransFIcon" Angle="0"/> </TextBlock.RenderTransform> </TextBlock> </Viewbox> </Grid> <ControlTemplate.Triggers> <!--激活狀態(tài)--> <Trigger Property="IsActive" Value="true"> <Setter Property="Visibility" Value="Visible" TargetName="FIcon"/> <Trigger.EnterActions> <BeginStoryboard > <Storyboard > <DoubleAnimation RepeatBehavior="Forever" Storyboard.TargetName="TransFIcon" Storyboard.TargetProperty="Angle" To="360" Duration="0:0:2.5"/> </Storyboard> </BeginStoryboard> </Trigger.EnterActions> <Trigger.ExitActions> <BeginStoryboard > <Storyboard > <DoubleAnimation RepeatBehavior="Forever" Storyboard.TargetName="TransFIcon" Storyboard.TargetProperty="Angle" To="0" Duration="0"/> </Storyboard> </BeginStoryboard> </Trigger.ExitActions> </Trigger> <!--非激活狀態(tài)--> <Trigger Property="IsActive" Value="false"> <Setter Property="Visibility" Value="Collapsed" TargetName="FIcon"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> 使用示例: <CheckBox VerticalAlignment="Center" x:Name="cbActive2" IsChecked="True" Margin="5">IsActive</CheckBox> <core:BusyBox Width="80" Height="80" Foreground="White" Background="Red" Margin="5" IsActive="{Binding IsChecked ,ElementName=cbActive2}" /> <core:BusyBox Width="30" Height="30" Foreground="White" Background="Red" Margin="5" IsActive="{Binding IsChecked ,ElementName=cbActive2}" />
三.Win8/win10效果忙碌狀態(tài)控件ProgressRing 這是網(wǎng)上一個(gè)開源項(xiàng)目里的控件,項(xiàng)目地址:http:///,。不做多介紹了,,效果圖:
后臺(tái)C#代碼: [TemplateVisualState(Name = "Large", GroupName = "SizeStates")] [TemplateVisualState(Name = "Small", GroupName = "SizeStates")] [TemplateVisualState(Name = "Inactive", GroupName = "ActiveStates")] [TemplateVisualState(Name = "Active", GroupName = "ActiveStates")] public class ProgressRing : Control { public static readonly DependencyProperty BindableWidthProperty = DependencyProperty.Register("BindableWidth", typeof(double), typeof(ProgressRing), new PropertyMetadata(default(double), BindableWidthCallback)); public static readonly DependencyProperty IsActiveProperty = DependencyProperty.Register("IsActive", typeof(bool), typeof(ProgressRing), new FrameworkPropertyMetadata(default(bool), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, IsActiveChanged)); public static readonly DependencyProperty IsLargeProperty = DependencyProperty.Register("IsLarge", typeof(bool), typeof(ProgressRing), new PropertyMetadata(true, IsLargeChangedCallback)); public static readonly DependencyProperty MaxSideLengthProperty = DependencyProperty.Register("MaxSideLength", typeof(double), typeof(ProgressRing), new PropertyMetadata(default(double))); public static readonly DependencyProperty EllipseDiameterProperty = DependencyProperty.Register("EllipseDiameter", typeof(double), typeof(ProgressRing), new PropertyMetadata(default(double))); public static readonly DependencyProperty EllipseOffsetProperty = DependencyProperty.Register("EllipseOffset", typeof(Thickness), typeof(ProgressRing), new PropertyMetadata(default(Thickness))); private List<Action> _deferredActions = new List<Action>(); static ProgressRing() { DefaultStyleKeyProperty.OverrideMetadata(typeof(ProgressRing), new FrameworkPropertyMetadata(typeof(ProgressRing))); VisibilityProperty.OverrideMetadata(typeof(ProgressRing), new FrameworkPropertyMetadata( new PropertyChangedCallback( (ringObject, e) => { if (e.NewValue != e.OldValue) { var ring = (ProgressRing)ringObject; //auto set IsActive to false if we're hiding it. if ((Visibility)e.NewValue != Visibility.Visible) { //sets the value without overriding it's binding (if any). ring.SetCurrentValue(ProgressRing.IsActiveProperty, false); } else { // #1105 don't forget to re-activate ring.IsActive = true; } } }))); } public ProgressRing() { SizeChanged += OnSizeChanged; } public double MaxSideLength { get { return (double)GetValue(MaxSideLengthProperty); } private set { SetValue(MaxSideLengthProperty, value); } } public double EllipseDiameter { get { return (double)GetValue(EllipseDiameterProperty); } private set { SetValue(EllipseDiameterProperty, value); } } public Thickness EllipseOffset { get { return (Thickness)GetValue(EllipseOffsetProperty); } private set { SetValue(EllipseOffsetProperty, value); } } public double BindableWidth { get { return (double)GetValue(BindableWidthProperty); } private set { SetValue(BindableWidthProperty, value); } } public bool IsActive { get { return (bool)GetValue(IsActiveProperty); } set { SetValue(IsActiveProperty, value); } } public bool IsLarge { get { return (bool)GetValue(IsLargeProperty); } set { SetValue(IsLargeProperty, value); } } private static void BindableWidthCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs) { var ring = dependencyObject as ProgressRing; if (ring == null) return; var action = new Action(() => { ring.SetEllipseDiameter( (double)dependencyPropertyChangedEventArgs.NewValue); ring.SetEllipseOffset( (double)dependencyPropertyChangedEventArgs.NewValue); ring.SetMaxSideLength( (double)dependencyPropertyChangedEventArgs.NewValue); }); if (ring._deferredActions != null) ring._deferredActions.Add(action); else action(); } private void SetMaxSideLength(double width) { MaxSideLength = width <= 20 ? 20 : width; } private void SetEllipseDiameter(double width) { EllipseDiameter = width / 8; } private void SetEllipseOffset(double width) { EllipseOffset = new Thickness(0, width / 2, 0, 0); } private static void IsLargeChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs) { var ring = dependencyObject as ProgressRing; if (ring == null) return; ring.UpdateLargeState(); } private void UpdateLargeState() { Action action; if (IsLarge) action = () => VisualStateManager.GoToState(this, "Large", true); else action = () => VisualStateManager.GoToState(this, "Small", true); if (_deferredActions != null) _deferredActions.Add(action); else action(); } private void OnSizeChanged(object sender, SizeChangedEventArgs sizeChangedEventArgs) { BindableWidth = ActualWidth; } private static void IsActiveChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs) { var ring = dependencyObject as ProgressRing; if (ring == null) return; ring.UpdateActiveState(); } private void UpdateActiveState() { Action action; if (IsActive) action = () => VisualStateManager.GoToState(this, "Active", true); else action = () => VisualStateManager.GoToState(this, "Inactive", true); if (_deferredActions != null) _deferredActions.Add(action); else action(); } public override void OnApplyTemplate() { //make sure the states get updated UpdateLargeState(); UpdateActiveState(); base.OnApplyTemplate(); if (_deferredActions != null) foreach (var action in _deferredActions) action(); _deferredActions = null; } } internal class WidthToMaxSideLengthConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (value is double) { var width = (double)value; return width <= 20 ? 20 : width; } return null; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } } 樣式代碼: <Style TargetType="local:ProgressRing"> <Setter Property="Foreground" Value="White" /> <Setter Property="IsHitTestVisible" Value="False" /> <Setter Property="HorizontalAlignment" Value="Center" /> <Setter Property="VerticalAlignment" Value="Center" /> <Setter Property="MinHeight" Value="20" /> <Setter Property="MinWidth" Value="20" /> <Setter Property="Height" Value="60" /> <Setter Property="Width" Value="60" /> <Setter Property="IsTabStop" Value="False" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="local:ProgressRing"> <Border Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}"> <Border.Resources> <Style x:Key="ProgressRingEllipseStyle" TargetType="Ellipse"> <Setter Property="Opacity" Value="0" /> <Setter Property="HorizontalAlignment" Value="Left" /> <Setter Property="VerticalAlignment" Value="Top" /> </Style> </Border.Resources> <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="SizeStates"> <VisualState x:Name="Large"> <Storyboard> <ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetName="SixthCircle" Storyboard.TargetProperty="Visibility"> <DiscreteObjectKeyFrame KeyTime="0"> <DiscreteObjectKeyFrame.Value> <Visibility>Visible</Visibility> </DiscreteObjectKeyFrame.Value> </DiscreteObjectKeyFrame> </ObjectAnimationUsingKeyFrames> </Storyboard> </VisualState> <VisualState x:Name="Small" /> </VisualStateGroup> <VisualStateGroup x:Name="ActiveStates"> <VisualState x:Name="Inactive" /> <VisualState x:Name="Active"> <Storyboard RepeatBehavior="Forever"> <ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetName="Ring" Storyboard.TargetProperty="Visibility"> <DiscreteObjectKeyFrame KeyTime="0"> <DiscreteObjectKeyFrame.Value> <Visibility>Visible</Visibility> </DiscreteObjectKeyFrame.Value> </DiscreteObjectKeyFrame> </ObjectAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetName="E1" Storyboard.TargetProperty="Opacity" BeginTime="0"> <DiscreteDoubleKeyFrame KeyTime="0" Value="1" /> <DiscreteDoubleKeyFrame KeyTime="0:0:3.21" Value="1" /> <DiscreteDoubleKeyFrame KeyTime="0:0:3.22" Value="0" /> <DiscreteDoubleKeyFrame KeyTime="0:0:3.47" Value="0" /> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetName="E2" Storyboard.TargetProperty="Opacity" BeginTime="00:00:00.167"> <DiscreteDoubleKeyFrame KeyTime="0" Value="1" /> <DiscreteDoubleKeyFrame KeyTime="0:0:3.21" Value="1" /> <DiscreteDoubleKeyFrame KeyTime="0:0:3.22" Value="0" /> <DiscreteDoubleKeyFrame KeyTime="0:0:3.47" Value="0" /> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetName="E3" Storyboard.TargetProperty="Opacity" BeginTime="00:00:00.334"> <DiscreteDoubleKeyFrame KeyTime="0" Value="1" /> <DiscreteDoubleKeyFrame KeyTime="0:0:3.21" Value="1" /> <DiscreteDoubleKeyFrame KeyTime="0:0:3.22" Value="0" /> <DiscreteDoubleKeyFrame KeyTime="0:0:3.47" Value="0" /> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetName="E4" Storyboard.TargetProperty="Opacity" BeginTime="00:00:00.501"> <DiscreteDoubleKeyFrame KeyTime="0" Value="1" /> <DiscreteDoubleKeyFrame KeyTime="0:0:3.21" Value="1" /> <DiscreteDoubleKeyFrame KeyTime="0:0:3.22" Value="0" /> <DiscreteDoubleKeyFrame KeyTime="0:0:3.47" Value="0" /> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetName="E5" Storyboard.TargetProperty="Opacity" BeginTime="00:00:00.668"> <DiscreteDoubleKeyFrame KeyTime="0" Value="1" /> <DiscreteDoubleKeyFrame KeyTime="0:0:3.21" Value="1" /> <DiscreteDoubleKeyFrame KeyTime="0:0:3.22" Value="0" /> <DiscreteDoubleKeyFrame KeyTime="0:0:3.47" Value="0" /> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetName="E6" Storyboard.TargetProperty="Opacity" BeginTime="00:00:00.835"> <DiscreteDoubleKeyFrame KeyTime="0" Value="1" /> <DiscreteDoubleKeyFrame KeyTime="0:0:3.21" Value="1" /> <DiscreteDoubleKeyFrame KeyTime="0:0:3.22" Value="0" /> <DiscreteDoubleKeyFrame KeyTime="0:0:3.47" Value="0" /> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetName="E1R" BeginTime="0" Storyboard.TargetProperty="Angle"> <SplineDoubleKeyFrame KeyTime="0" Value="-110" KeySpline="0.13,0.21,0.1,0.7" /> <SplineDoubleKeyFrame KeyTime="0:0:0.433" Value="10" KeySpline="0.02,0.33,0.38,0.77" /> <SplineDoubleKeyFrame KeyTime="0:0:1.2" Value="93" /> <SplineDoubleKeyFrame KeyTime="0:0:1.617" Value="205" KeySpline="0.57,0.17,0.95,0.75" /> <SplineDoubleKeyFrame KeyTime="0:0:2.017" Value="357" KeySpline="0,0.19,0.07,0.72" /> <SplineDoubleKeyFrame KeyTime="0:0:2.783" Value="439" /> <SplineDoubleKeyFrame KeyTime="0:0:3.217" Value="585" KeySpline="0,0,0.95,0.37" /> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetName="E2R" BeginTime="00:00:00.167" Storyboard.TargetProperty="Angle"> <SplineDoubleKeyFrame KeyTime="0" Value="-116" KeySpline="0.13,0.21,0.1,0.7" /> <SplineDoubleKeyFrame KeyTime="0:0:0.433" Value="4" KeySpline="0.02,0.33,0.38,0.77" /> <SplineDoubleKeyFrame KeyTime="0:0:1.2" Value="87" /> <SplineDoubleKeyFrame KeyTime="0:0:1.617" Value="199" KeySpline="0.57,0.17,0.95,0.75" /> <SplineDoubleKeyFrame KeyTime="0:0:2.017" Value="351" KeySpline="0,0.19,0.07,0.72" /> <SplineDoubleKeyFrame KeyTime="0:0:2.783" Value="433" /> <SplineDoubleKeyFrame KeyTime="0:0:3.217" Value="579" KeySpline="0,0,0.95,0.37" /> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetName="E3R" BeginTime="00:00:00.334" Storyboard.TargetProperty="Angle"> <SplineDoubleKeyFrame KeyTime="0" Value="-122" KeySpline="0.13,0.21,0.1,0.7" /> <SplineDoubleKeyFrame KeyTime="0:0:0.433" Value="-2" KeySpline="0.02,0.33,0.38,0.77" /> <SplineDoubleKeyFrame KeyTime="0:0:1.2" Value="81" /> <SplineDoubleKeyFrame KeyTime="0:0:1.617" Value="193" KeySpline="0.57,0.17,0.95,0.75" /> <SplineDoubleKeyFrame KeyTime="0:0:2.017" Value="345" KeySpline="0,0.19,0.07,0.72" /> <SplineDoubleKeyFrame KeyTime="0:0:2.783" Value="427" /> <SplineDoubleKeyFrame KeyTime="0:0:3.217" Value="573" KeySpline="0,0,0.95,0.37" /> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetName="E4R" BeginTime="00:00:00.501" Storyboard.TargetProperty="Angle"> <SplineDoubleKeyFrame KeyTime="0" Value="-128" KeySpline="0.13,0.21,0.1,0.7" /> <SplineDoubleKeyFrame KeyTime="0:0:0.433" Value="-8" KeySpline="0.02,0.33,0.38,0.77" /> <SplineDoubleKeyFrame KeyTime="0:0:1.2" Value="75" /> <SplineDoubleKeyFrame KeyTime="0:0:1.617" Value="187" KeySpline="0.57,0.17,0.95,0.75" /> <SplineDoubleKeyFrame KeyTime="0:0:2.017" Value="339" KeySpline="0,0.19,0.07,0.72" /> <SplineDoubleKeyFrame KeyTime="0:0:2.783" Value="421" /> <SplineDoubleKeyFrame KeyTime="0:0:3.217" Value="567" KeySpline="0,0,0.95,0.37" /> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetName="E5R" BeginTime="00:00:00.668" Storyboard.TargetProperty="Angle"> <SplineDoubleKeyFrame KeyTime="0" Value="-134" KeySpline="0.13,0.21,0.1,0.7" /> <SplineDoubleKeyFrame KeyTime="0:0:0.433" Value="-14" KeySpline="0.02,0.33,0.38,0.77" /> <SplineDoubleKeyFrame KeyTime="0:0:1.2" Value="69" /> <SplineDoubleKeyFrame KeyTime="0:0:1.617" Value="181" KeySpline="0.57,0.17,0.95,0.75" /> <SplineDoubleKeyFrame KeyTime="0:0:2.017" Value="331" KeySpline="0,0.19,0.07,0.72" /> <SplineDoubleKeyFrame KeyTime="0:0:2.783" Value="415" /> <SplineDoubleKeyFrame KeyTime="0:0:3.217" Value="561" KeySpline="0,0,0.95,0.37" /> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetName="E6R" BeginTime="00:00:00.835" Storyboard.TargetProperty="Angle"> <SplineDoubleKeyFrame KeyTime="0" Value="-140" KeySpline="0.13,0.21,0.1,0.7" /> <SplineDoubleKeyFrame KeyTime="0:0:0.433" Value="-20" KeySpline="0.02,0.33,0.38,0.77" /> <SplineDoubleKeyFrame KeyTime="0:0:1.2" Value="63" /> <SplineDoubleKeyFrame KeyTime="0:0:1.617" Value="175" KeySpline="0.57,0.17,0.95,0.75" /> <SplineDoubleKeyFrame KeyTime="0:0:2.017" Value="325" KeySpline="0,0.19,0.07,0.72" /> <SplineDoubleKeyFrame KeyTime="0:0:2.783" Value="409" /> <SplineDoubleKeyFrame KeyTime="0:0:3.217" Value="555" KeySpline="0,0,0.95,0.37" /> </DoubleAnimationUsingKeyFrames> </Storyboard> </VisualState> </VisualStateGroup> </VisualStateManager.VisualStateGroups> <Grid x:Name="Ring" Margin="{TemplateBinding Padding}" MaxWidth="{Binding MaxSideLength, RelativeSource={RelativeSource Mode=TemplatedParent}}" MaxHeight="{Binding MaxSideLength, RelativeSource={RelativeSource Mode=TemplatedParent}}" Visibility="Collapsed" RenderTransformOrigin=".5,.5" FlowDirection="LeftToRight"> <Canvas RenderTransformOrigin=".5,.5"> <Canvas.RenderTransform> <RotateTransform x:Name="E1R" /> </Canvas.RenderTransform> <Ellipse x:Name="E1" Style="{StaticResource ProgressRingEllipseStyle}" Width="{Binding EllipseDiameter, RelativeSource={RelativeSource Mode=TemplatedParent}}" Height="{Binding EllipseDiameter, RelativeSource={RelativeSource Mode=TemplatedParent}}" Margin="{Binding EllipseOffset, RelativeSource={RelativeSource Mode=TemplatedParent}}" Fill="{TemplateBinding Foreground}" /> </Canvas> <Canvas RenderTransformOrigin=".5,.5"> <Canvas.RenderTransform> <RotateTransform x:Name="E2R" /> </Canvas.RenderTransform> <Ellipse x:Name="E2" Style="{StaticResource ProgressRingEllipseStyle}" Width="{Binding EllipseDiameter, RelativeSource={RelativeSource Mode=TemplatedParent}}" Height="{Binding EllipseDiameter, RelativeSource={RelativeSource Mode=TemplatedParent}}" Margin="{Binding EllipseOffset, RelativeSource={RelativeSource Mode=TemplatedParent}}" Fill="{TemplateBinding Foreground}" /> </Canvas> <Canvas RenderTransformOrigin=".5,.5"> <Canvas.RenderTransform> <RotateTransform x:Name="E3R" /> </Canvas.RenderTransform> <Ellipse x:Name="E3" Style="{StaticResource ProgressRingEllipseStyle}" Width="{Binding EllipseDiameter, RelativeSource={RelativeSource Mode=TemplatedParent}}" Height="{Binding EllipseDiameter, RelativeSource={RelativeSource Mode=TemplatedParent}}" Margin="{Binding EllipseOffset, RelativeSource={RelativeSource Mode=TemplatedParent}}" Fill="{TemplateBinding Foreground}" /> </Canvas> <Canvas RenderTransformOrigin=".5,.5"> <Canvas.RenderTransform> <RotateTransform x:Name="E4R" /> </Canvas.RenderTransform> <Ellipse x:Name="E4" Style="{StaticResource ProgressRingEllipseStyle}" Width="{Binding EllipseDiameter, RelativeSource={RelativeSource Mode=TemplatedParent}}" Height="{Binding EllipseDiameter, RelativeSource={RelativeSource Mode=TemplatedParent}}" Margin="{Binding EllipseOffset, RelativeSource={RelativeSource Mode=TemplatedParent}}" Fill="{TemplateBinding Foreground}" /> </Canvas> <Canvas RenderTransformOrigin=".5,.5"> <Canvas.RenderTransform> <RotateTransform x:Name="E5R" /> </Canvas.RenderTransform> <Ellipse x:Name="E5" Style="{StaticResource ProgressRingEllipseStyle}" Width="{Binding EllipseDiameter, RelativeSource={RelativeSource Mode=TemplatedParent}}" Height="{Binding EllipseDiameter, RelativeSource={RelativeSource Mode=TemplatedParent}}" Margin="{Binding EllipseOffset, RelativeSource={RelativeSource Mode=TemplatedParent}}" Fill="{TemplateBinding Foreground}" /> </Canvas> <Canvas RenderTransformOrigin=".5,.5" Visibility="Collapsed" x:Name="SixthCircle"> <Canvas.RenderTransform> <RotateTransform x:Name="E6R" /> </Canvas.RenderTransform> <Ellipse x:Name="E6" Style="{StaticResource ProgressRingEllipseStyle}" Width="{Binding EllipseDiameter, RelativeSource={RelativeSource Mode=TemplatedParent}}" Height="{Binding EllipseDiameter, RelativeSource={RelativeSource Mode=TemplatedParent}}" Margin="{Binding EllipseOffset, RelativeSource={RelativeSource Mode=TemplatedParent}}" Fill="{TemplateBinding Foreground}" /> </Canvas> </Grid> </Border> </ControlTemplate> </Setter.Value> </Setter> </Style> 使用示例: <CheckBox VerticalAlignment="Center" x:Name="cbActive" Margin="5" IsChecked="True">IsActive</CheckBox> <core:ProgressRing Width="80" Height="80" Foreground="Red" Margin="5" IsActive="{Binding IsChecked ,ElementName=cbActive}" />
四.彈出異步等待框WaitingBox 效果圖:
使用的是一個(gè)模式窗體,,異步執(zhí)行傳入的操作,實(shí)現(xiàn)的比較簡(jiǎn)單,,沒有做異常處理,。另外一個(gè)缺陷就是沒有支持取消操作。后臺(tái)C#代碼: /// <summary> /// 簡(jiǎn)單等待框 /// </summary> public partial class WaitingBox : Window { public string Text { get { return this.txtMessage.Text; } set { this.txtMessage.Text = value; } } private Action _Callback; public WaitingBox(Action callback) { InitializeComponent(); this._Callback = callback; this.Loaded += WaitingBox_Loaded; } void WaitingBox_Loaded(object sender, RoutedEventArgs e) { this._Callback.BeginInvoke(this.OnComplate, null); } private void OnComplate(IAsyncResult ar) { this.Dispatcher.Invoke(new Action(() => { this.Close(); })); } /// <summary> /// 顯示等待框,,owner指定宿主視圖元素,,callback為需要執(zhí)行的方法體(需要自己做異常處理)。 /// 目前等等框?yàn)槟J酱绑w /// </summary> public static void Show(FrameworkElement owner, Action callback, string mes = "有一種幸福,,叫做等待...") { WaitingBox win = new WaitingBox(callback); Window pwin = Window.GetWindow(owner); win.Owner = pwin; win.Text = mes; var loc = owner.PointToScreen(new Point()); win.Left = loc.X + (owner.ActualWidth - win.Width) / 2; win.Top = loc.Y + (owner.ActualHeight - win.Height) / 2; win.ShowDialog(); } } 樣式代碼: <Window x:Class="System.Windows.WaitingBox" x:Name="wb" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" AllowsTransparency="True" WindowStyle="None" WindowStartupLocation="Manual" ShowInTaskbar="False" Background="Transparent" Title="WaitingBox" Height="110" Width="260"> <Grid> <!--Background="{Binding Path=Background,ElementName=wb}"--> <Border Background="{StaticResource WaitingBoxBackground}" Opacity="0.89" CornerRadius="1" Effect="{StaticResource WindowDropShadow}"></Border> <StackPanel VerticalAlignment="Center" Orientation="Horizontal" HorizontalAlignment="Center" Margin="5"> <TextBlock Text="" x:Name="FIcon" FontSize="50" Style="{StaticResource FIcon}" RenderTransformOrigin="0.5,0.5" Margin="3"> <TextBlock.RenderTransform> <RotateTransform x:Name="TransFIcon" Angle="0"/> </TextBlock.RenderTransform> </TextBlock> <TextBlock x:Name="txtMessage" Margin="2,10,15,10" Width="160" VerticalAlignment="Center" TextWrapping="Wrap">Loading...</TextBlock> </StackPanel> </Grid> <Window.Triggers> <EventTrigger RoutedEvent="Window.Loaded"> <BeginStoryboard > <Storyboard > <DoubleAnimation RepeatBehavior="Forever" Storyboard.TargetName="TransFIcon" Storyboard.TargetProperty="Angle" To="360" Duration="0:0:2.5"/> </Storyboard> </BeginStoryboard> </EventTrigger> </Window.Triggers> </Window> 使用比較簡(jiǎn)單,,示例: WaitingBox.Show(this, () => { System.Threading.Thread.Sleep(3000); },"正在玩命的加載,請(qǐng)稍后..."); var res = MessageBoxX.Question("已經(jīng)完了,?");
附錄:參考引用 WPF自定義控件與樣式(1)-矢量字體圖標(biāo)(iconfont) WPF自定義控件與樣式(3)-TextBox & RichTextBox & PasswordBox樣式,、水印、Label標(biāo)簽,、功能擴(kuò)展 WPF自定義控件與樣式(4)-CheckBox/RadioButton自定義樣式 WPF自定義控件與樣式(5)-Calendar/DatePicker日期控件自定義樣式及擴(kuò)展 WPF自定義控件與樣式(6)-ScrollViewer與ListBox自定義樣式 WPF自定義控件與樣式(7)-列表控件DataGrid與ListView自定義樣式 WPF自定義控件與樣式(8)-ComboBox與自定義多選控件MultComboBox WPF自定義控件與樣式(9)-樹控件TreeView與菜單Menu-ContextMenu WPF自定義控件與樣式(10)-進(jìn)度控件ProcessBar自定義樣
版權(quán)所有,,文章來源:http://www.cnblogs.com/anding 個(gè)人能力有限,本文內(nèi)容僅供學(xué)習(xí),、探討,,歡迎指正、交流,。 |
|