Эх сурвалжийг харах

[新增]用户控件Idcontrol,LedControl,ParameterControl,StatusControl等。

Jiangsheng 2 долоо хоног өмнө
parent
commit
bfcd8f4bdf

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 4 - 255
Readme.md


+ 30 - 1
SKMC.UI.DesignApp/Views/BasicControlsView.xaml

@@ -9,7 +9,7 @@
              xmlns:prism="http://prismlibrary.com/"
              prism:ViewModelLocator.AutoWireViewModel="True"
              mc:Ignorable="d" 
-             d:DesignHeight="800" d:DesignWidth="1000">
+             d:DesignHeight="800" d:DesignWidth="1200">
     <Grid>
         <Border Style="{StaticResource Border.Base}"
                 Background="Transparent">
@@ -233,6 +233,35 @@
                         </ListView.View>
                     </ListView>
                 </StackPanel>
+                <StackPanel>
+                    <StackPanel Orientation="Horizontal">
+                        <Label Content="LedControl" Foreground="{StaticResource Brush.Text}"/>
+                        <u:LedControl IsBlinking="True" Width="20" Height="20"/>
+                    </StackPanel>
+                    <u:StatusControl IsActive="True" IsBlinking="True" 
+                                     IsSecondStatusActive="True" 
+                                     IsSecondStatusBlinking="True"
+                                     Label="StatusControl"
+                                     Height="25"
+                                     Margin="5"
+                                     CornerRadius="3"/>
+                    <StackPanel Orientation="Horizontal">
+                        <Label Content="WaitIconControl" Foreground="{StaticResource Brush.Text}"/>
+                        <u:WaitIconControl ShowWait="True" Margin="3"/>
+                    </StackPanel>
+                    <StackPanel Orientation="Horizontal">
+                        <Label Content="IdControl" Foreground="{StaticResource Brush.Text}"/>
+                        <u:IdControl Id="1" Width="15" Height="15" Foreground="AliceBlue"/>
+                        <u:IdControl Id="2" Width="15" Height="15" Foreground="AliceBlue"/>
+                        <u:IdControl Id="3" Width="15" Height="15" Foreground="AliceBlue"/>
+                        <u:IdControl Id="4" Width="15" Height="15" Foreground="AliceBlue"/>
+                    </StackPanel>
+                    <u:ParameterControl ParameterTitle="ParameterControl" 
+                                        ParameterValue="50.0" 
+                                        ParameterUnit="mm"
+                                        Width="210"
+                                        Height="30"/>
+                </StackPanel>
             </StackPanel>
         </Border>
     </Grid>

+ 1 - 0
SKMC.UI/Converters/Converters.xaml

@@ -8,4 +8,5 @@
     <c:BooleanToInvertedBooleanConverter x:Key="BooleanToInvertedBooleanConverter" />
     <c:DateTimeToStringConverter x:Key="DateTimeToStringConverter" />
     <c:EnumDescriptionConverter x:Key="EnumDescriptionConverter" />
+    <c:UnitEnumToStringConverter x:Key="UnitEnumToStringConverter" />
 </ResourceDictionary>

+ 27 - 0
SKMC.UI/Converters/UnitEnumToStringConverter.cs

@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+
+namespace SKMC.UI.Converters
+{
+    public class UnitEnumToStringConverter
+    {
+        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+        {
+            if (value == null)
+            {
+                return DependencyProperty.UnsetValue;
+            }
+            return value;
+        }
+
+        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+        {
+            throw new NotSupportedException();
+        }
+    }
+}

+ 1 - 0
SKMC.UI/FrameWork.xaml

@@ -27,6 +27,7 @@
         <ResourceDictionary Source="pack://application:,,,/SKMC.UI;component/Styles/ProgressBar.xaml" />
         <ResourceDictionary Source="pack://application:,,,/SKMC.UI;component/Styles/Control.xaml" />
         <ResourceDictionary Source="pack://application:,,,/SKMC.UI;component/Styles/Expander.xaml" />
+        <ResourceDictionary Source="pack://application:,,,/SKMC.UI;component/Styles/Label.xaml" />
         <!--  Styles  -->
     </ResourceDictionary.MergedDictionaries>
 </ResourceDictionary>

+ 40 - 0
SKMC.UI/SKMC.UI.csproj

@@ -56,6 +56,7 @@
     <Compile Include="Converters\DateTimeToStringConverter.cs" />
     <Compile Include="Converters\EnumDescriptionConverter.cs" />
     <Compile Include="Converters\StringToBooleanConverter.cs" />
+    <Compile Include="Converters\UnitEnumToStringConverter.cs" />
     <Compile Include="CustomControls\SKButton.cs" />
     <Compile Include="CustomControls\SKCheckBox.cs" />
     <Compile Include="CustomControls\SKRadioButton.cs" />
@@ -74,9 +75,24 @@
       <DesignTimeSharedInput>True</DesignTimeSharedInput>
     </Compile>
     <Compile Include="Themes\ThemeManager.cs" />
+    <Compile Include="UserControls\IdControl.xaml.cs">
+      <DependentUpon>IdControl.xaml</DependentUpon>
+    </Compile>
+    <Compile Include="UserControls\LedControl.xaml.cs">
+      <DependentUpon>LedControl.xaml</DependentUpon>
+    </Compile>
     <Compile Include="UserControls\NumpadControl.xaml.cs">
       <DependentUpon>NumpadControl.xaml</DependentUpon>
     </Compile>
+    <Compile Include="UserControls\ParameterControl.xaml.cs">
+      <DependentUpon>ParameterControl.xaml</DependentUpon>
+    </Compile>
+    <Compile Include="UserControls\StatusControl.xaml.cs">
+      <DependentUpon>StatusControl.xaml</DependentUpon>
+    </Compile>
+    <Compile Include="UserControls\WaitIconControl.xaml.cs">
+      <DependentUpon>WaitIconControl.xaml</DependentUpon>
+    </Compile>
     <Compile Include="ValidationRules\DateTimeRule.cs" />
     <Compile Include="ValidationRules\RangeValidationRule.cs" />
     <EmbeddedResource Include="Properties\Resources.resx">
@@ -105,6 +121,10 @@
       <SubType>Designer</SubType>
       <Generator>MSBuild:Compile</Generator>
     </Page>
+    <Page Include="Styles\Label.xaml">
+      <SubType>Designer</SubType>
+      <Generator>MSBuild:Compile</Generator>
+    </Page>
     <Page Include="Styles\PasswordBox.xaml">
       <SubType>Designer</SubType>
       <Generator>MSBuild:Compile</Generator>
@@ -113,10 +133,30 @@
       <SubType>Designer</SubType>
       <Generator>MSBuild:Compile</Generator>
     </Page>
+    <Page Include="UserControls\IdControl.xaml">
+      <SubType>Designer</SubType>
+      <Generator>MSBuild:Compile</Generator>
+    </Page>
+    <Page Include="UserControls\LedControl.xaml">
+      <SubType>Designer</SubType>
+      <Generator>MSBuild:Compile</Generator>
+    </Page>
     <Page Include="UserControls\NumpadControl.xaml">
       <Generator>MSBuild:Compile</Generator>
       <SubType>Designer</SubType>
     </Page>
+    <Page Include="UserControls\ParameterControl.xaml">
+      <SubType>Designer</SubType>
+      <Generator>MSBuild:Compile</Generator>
+    </Page>
+    <Page Include="UserControls\StatusControl.xaml">
+      <SubType>Designer</SubType>
+      <Generator>MSBuild:Compile</Generator>
+    </Page>
+    <Page Include="UserControls\WaitIconControl.xaml">
+      <SubType>Designer</SubType>
+      <Generator>MSBuild:Compile</Generator>
+    </Page>
     <Resource Include="Assets\Brushes.xaml">
       <SubType>Designer</SubType>
       <Generator>MSBuild:Compile</Generator>

+ 108 - 0
SKMC.UI/Styles/Label.xaml

@@ -0,0 +1,108 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
+    <Style
+		TargetType="{x:Type Label}"
+		x:Key="Label.Base">
+        <Setter
+			Property="FontFamily"
+			Value="{DynamicResource FontFamily.Global}" />
+        <Setter
+			Property="FontSize"
+			Value="{DynamicResource FontSize.Body}" />
+        <Setter
+			Property="Foreground"
+			Value="{DynamicResource Brush.Text}" />
+        <Setter
+			Property="HorizontalAlignment"
+			Value="Left" />
+        <Setter
+			Property="Margin"
+			Value="5" />
+        <Setter
+			Property="FrameworkElement.ToolTip"
+			Value="{Binding Content, RelativeSource={RelativeSource Self}}" />
+    </Style>
+    <Style
+		BasedOn="{StaticResource Label.Base}"
+		TargetType="{x:Type Label}"
+		x:Key="Label.PageTitle">
+        <Setter
+			Property="FontSize"
+			Value="{DynamicResource FontSize.Headline}" />
+        <Setter
+			Property="FontWeight"
+			Value="Bold" />
+        <Setter
+			Property="Margin"
+			Value="5,32,5,64" />
+    </Style>
+    <Style
+		BasedOn="{StaticResource Label.Base}"
+		TargetType="{x:Type Label}"
+		x:Key="Label.RecipeName">
+        <Setter
+			Property="Template">
+            <Setter.Value>
+                <ControlTemplate
+					TargetType="{x:Type Label}">
+                    <TextBlock
+						HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
+						VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
+						Text="{TemplateBinding Content}" />
+                </ControlTemplate>
+            </Setter.Value>
+        </Setter>
+    </Style>
+    <Style
+		BasedOn="{StaticResource Label.Base}"
+		TargetType="{x:Type Label}"
+		x:Key="Label.ComponentName">
+        <Setter
+			Property="FontSize"
+			Value="{DynamicResource FontSize.Title}" />
+        <Setter
+			Property="FontWeight"
+			Value="Bold" />
+    </Style>
+    <Style
+		BasedOn="{StaticResource Label.Base}"
+		TargetType="{x:Type Label}"
+		x:Key="{x:Type Label}" />
+    <Style
+		BasedOn="{StaticResource Label.Base}"
+		TargetType="{x:Type Label}"
+		x:Key="Label.TrimmingLabel">
+        <Setter
+			Property="Template">
+            <Setter.Value>
+                <ControlTemplate
+					TargetType="{x:Type Label}">
+                    <Border
+						Padding="{TemplateBinding Padding}"
+						Background="{TemplateBinding Background}"
+						BorderBrush="{TemplateBinding BorderBrush}"
+						BorderThickness="{TemplateBinding BorderThickness}"
+						SnapsToDevicePixels="true">
+                        <TextBlock
+							HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
+							VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
+							Text="{TemplateBinding Content}"
+							TextTrimming="CharacterEllipsis"
+							TextWrapping="NoWrap" />
+                    </Border>
+                </ControlTemplate>
+            </Setter.Value>
+        </Setter>
+    </Style>
+    <Style
+		BasedOn="{StaticResource Label.TrimmingLabel}"
+		TargetType="{x:Type Label}"
+		x:Key="Label.TrimmingLabelBold">
+        <Setter
+			Property="FontSize"
+			Value="{DynamicResource FontSize.Title}" />
+        <Setter
+			Property="FontWeight"
+			Value="Bold" />
+    </Style>
+</ResourceDictionary>

+ 25 - 0
SKMC.UI/UserControls/IdControl.xaml

@@ -0,0 +1,25 @@
+<UserControl x:Class="SKMC.UI.UserControls.IdControl"
+             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:SKMC.UI.UserControls"
+             mc:Ignorable="d" 
+             d:DesignHeight="450" d:DesignWidth="800"
+             Name="parent">
+    <Grid>
+        <Ellipse
+			StrokeThickness="1"
+			Width="{Binding Width, ElementName=parent}"
+			Height="{Binding Height, ElementName=parent}"
+			Stroke="{Binding Foreground, ElementName=parent}" />
+        <TextBlock
+			HorizontalAlignment="Center"
+			VerticalAlignment="Center"
+			FontFamily="{StaticResource FontFamily.Global}"
+			FontWeight="Bold"
+			TextAlignment="Center"
+			Foreground="{Binding Foreground, ElementName=parent}"
+			Text="{Binding Id, ElementName=parent}" />
+    </Grid>
+</UserControl>

+ 40 - 0
SKMC.UI/UserControls/IdControl.xaml.cs

@@ -0,0 +1,40 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace SKMC.UI.UserControls
+{
+    /// <summary>
+    /// IdControl.xaml 的交互逻辑
+    /// </summary>
+    public partial class IdControl : UserControl
+    {
+        public int Id
+        {
+            get
+            {
+                return (int)base.GetValue(IdProperty);
+            }
+            set
+            {
+                base.SetValue(IdProperty, value);
+            }
+        }
+        public IdControl()
+        {
+            InitializeComponent();
+        }
+        public static readonly DependencyProperty IdProperty = DependencyProperty.Register("Id", typeof(int), typeof(IdControl));
+    }
+}

+ 61 - 0
SKMC.UI/UserControls/LedControl.xaml

@@ -0,0 +1,61 @@
+<UserControl x:Class="SKMC.UI.UserControls.LedControl"
+             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:SKMC.UI.UserControls"
+             mc:Ignorable="d" 
+             d:DesignHeight="450" d:DesignWidth="800"
+             Name="parent"
+	         Width="12"
+	         Height="12">
+    <Ellipse
+		Width="{Binding Width}"
+		Height="{Binding Height}"
+		DataContext="{Binding ElementName=parent}">
+        <FrameworkElement.Style>
+            <Style
+				TargetType="{x:Type Ellipse}">
+                <Style.Triggers>
+                    <DataTrigger
+						Value="True"
+						Binding="{Binding IsActive}">
+                        <Setter
+							Property="Fill"
+							Value="{Binding ActiveBrush}" />
+                    </DataTrigger>
+                    <DataTrigger
+						Value="False"
+						Binding="{Binding IsActive}">
+                        <Setter
+							Property="Fill"
+							Value="{Binding InactiveBrush}" />
+                    </DataTrigger>
+                    <DataTrigger
+						Value="True"
+						Binding="{Binding IsBlinking}">
+                        <Setter
+							Property="Fill"
+							Value="{Binding ActiveBrush}" />
+                        <TriggerBase.EnterActions>
+                            <BeginStoryboard
+								Name="BlinkingStoryboard"
+								Storyboard="{StaticResource Storyboard.Blinking}" />
+                        </TriggerBase.EnterActions>
+                    </DataTrigger>
+                    <DataTrigger
+						Value="False"
+						Binding="{Binding IsBlinking}">
+                        <TriggerBase.EnterActions>
+                            <StopStoryboard
+								BeginStoryboardName="BlinkingStoryboard" />
+                        </TriggerBase.EnterActions>
+                        <Setter
+							Property="UIElement.Opacity"
+							Value="1" />
+                    </DataTrigger>
+                </Style.Triggers>
+            </Style>
+        </FrameworkElement.Style>
+    </Ellipse>
+</UserControl>

+ 91 - 0
SKMC.UI/UserControls/LedControl.xaml.cs

@@ -0,0 +1,91 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace SKMC.UI.UserControls
+{
+    /// <summary>
+    /// LedControl.xaml 的交互逻辑
+    /// </summary>
+    public partial class LedControl : UserControl
+    {
+        /// <summary>
+        /// 激活画刷
+        /// </summary>
+        public SolidColorBrush ActiveBrush
+        {
+            get
+            {
+                return (SolidColorBrush)base.GetValue(ActiveBrushProperty);
+            }
+            set
+            {
+                base.SetValue(ActiveBrushProperty, value);
+            }
+        }
+        /// <summary>
+        /// 未激活画刷
+        /// </summary>
+        public SolidColorBrush InactiveBrush
+        {
+            get
+            {
+                return (SolidColorBrush)base.GetValue(InactiveBrushProperty);
+            }
+            set
+            {
+                base.SetValue(InactiveBrushProperty, value);
+            }
+        }
+        /// <summary>
+        /// 激活
+        /// </summary>
+        public bool IsActive
+        {
+            get
+            {
+                return (bool)base.GetValue(IsActiveProperty);
+            }
+            set
+            {
+                base.SetValue(IsActiveProperty, value);
+            }
+        }
+        /// <summary>
+        /// 是否闪烁
+        /// </summary>
+        public bool IsBlinking
+        {
+            get
+            {
+                return (bool)base.GetValue(IsBlinkingProperty);
+            }
+            set
+            {
+                base.SetValue(IsBlinkingProperty, value);
+            }
+        }
+        public LedControl()
+        {
+            InitializeComponent();
+        }
+        public static readonly DependencyProperty ActiveBrushProperty = DependencyProperty.Register("ActiveBrush", typeof(SolidColorBrush), typeof(LedControl), new PropertyMetadata(new BrushConverter().ConvertFromString("#00F976")));
+
+        public static readonly DependencyProperty InactiveBrushProperty = DependencyProperty.Register("InactiveBrush", typeof(SolidColorBrush), typeof(LedControl), new PropertyMetadata(new BrushConverter().ConvertFromString("#404040")));
+
+        public static readonly DependencyProperty IsActiveProperty = DependencyProperty.Register("IsActive", typeof(bool), typeof(LedControl));
+
+        public static readonly DependencyProperty IsBlinkingProperty = DependencyProperty.Register("IsBlinking", typeof(bool), typeof(LedControl));
+    }
+}

+ 53 - 0
SKMC.UI/UserControls/ParameterControl.xaml

@@ -0,0 +1,53 @@
+<UserControl x:Class="SKMC.UI.UserControls.ParameterControl"
+             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:SKMC.UI.UserControls"
+             mc:Ignorable="d" 
+             d:DesignHeight="450" d:DesignWidth="800"
+             Name="parent">
+    <Grid
+		DataContext="{Binding ElementName=parent}">
+        <Grid.ColumnDefinitions>
+            <ColumnDefinition
+				Width="Auto" />
+            <ColumnDefinition
+				Width="Auto" />
+            <ColumnDefinition
+				Width="Auto" />
+        </Grid.ColumnDefinitions>
+        <FrameworkElement.ToolTip>
+            <ToolTip
+				Background="{StaticResource Brush.DarkBackground}"
+				HasDropShadow="True">
+                <StackPanel
+					Orientation="Horizontal">
+                    <Label
+						Style="{StaticResource Label.Base}"
+						Content="{Binding ParameterValue}" />
+                    <Label
+						Style="{StaticResource Label.Base}"
+						Content="{Binding ParameterUnit}" />
+                </StackPanel>
+            </ToolTip>
+        </FrameworkElement.ToolTip>
+        <Label
+			Grid.Column="0"
+			Margin="0"
+			Style="{StaticResource Label.Base}"
+			Content="{Binding ParameterTitle}" />
+        <Label
+			Grid.Column="1"
+			Margin="0"
+			HorizontalContentAlignment="Right"
+			ContentStringFormat=" {0:F3}"
+			Style="{StaticResource Label.Base}"
+			Content="{Binding ParameterValue}" />
+        <Label
+			Grid.Column="2"
+			Margin="0"
+			Style="{StaticResource Label.Base}"
+			Content="{Binding ParameterUnit}" />
+    </Grid>
+</UserControl>

+ 68 - 0
SKMC.UI/UserControls/ParameterControl.xaml.cs

@@ -0,0 +1,68 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace SKMC.UI.UserControls
+{
+    /// <summary>
+    /// ParameterControl.xaml 的交互逻辑
+    /// </summary>
+    public partial class ParameterControl : UserControl
+    {
+        public string ParameterTitle
+        {
+            get
+            {
+                return (string)base.GetValue(ParameterControl.ParameterTitleProperty);
+            }
+            set
+            {
+                base.SetValue(ParameterControl.ParameterTitleProperty, value);
+            }
+        }
+
+        public double ParameterValue
+        {
+            get
+            {
+                return (double)base.GetValue(ParameterControl.ParameterValueProperty);
+            }
+            set
+            {
+                base.SetValue(ParameterControl.ParameterValueProperty, value);
+            }
+        }
+        public string ParameterUnit
+        {
+            get
+            {
+                return (string)base.GetValue(ParameterControl.ParameterUnitProperty);
+            }
+            set
+            {
+                base.SetValue(ParameterControl.ParameterUnitProperty, value);
+            }
+        }
+        public ParameterControl()
+        {
+            InitializeComponent();
+        }
+        public static readonly DependencyProperty ParameterTitleProperty = DependencyProperty.Register("ParameterTitle", typeof(string), typeof(ParameterControl), new PropertyMetadata("Power"));
+
+        public static readonly DependencyProperty ParameterValueProperty = DependencyProperty.Register("ParameterValue", typeof(double), typeof(ParameterControl), new PropertyMetadata(50.0));
+
+        public static readonly DependencyProperty ParameterUnitProperty = DependencyProperty.Register("ParameterUnit", typeof(string), typeof(ParameterControl), new PropertyMetadata("%"));
+    }
+
+}

+ 158 - 0
SKMC.UI/UserControls/StatusControl.xaml

@@ -0,0 +1,158 @@
+<UserControl x:Class="SKMC.UI.UserControls.StatusControl"
+             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:SKMC.UI.UserControls"
+             mc:Ignorable="d" 
+             d:DesignHeight="450" d:DesignWidth="800"
+             Name="parent"
+	         Height="32">
+    <Border
+		BorderBrush="{StaticResource Brush.Overlay12Percent}"
+		CornerRadius="{Binding CornerRadius}"
+		DataContext="{Binding ElementName=parent}">
+        <Grid>
+            <Grid.ColumnDefinitions>
+                <ColumnDefinition
+					Width="Auto" />
+                <ColumnDefinition
+					Width="Auto" />
+                <ColumnDefinition
+					Width="*" />
+            </Grid.ColumnDefinitions>
+            <Ellipse
+				Grid.Column="0"
+				Width="12"
+				Height="12"
+				Margin="8,0,0,0">
+                <FrameworkElement.Style>
+                    <Style
+						TargetType="{x:Type Ellipse}">
+                        <Style.Triggers>
+                            <DataTrigger
+								Value="True"
+								Binding="{Binding IsActive}">
+                                <Setter
+									Property="Fill"
+									Value="{Binding ActiveBrush}" />
+                            </DataTrigger>
+                            <DataTrigger
+								Value="False"
+								Binding="{Binding IsActive}">
+                                <Setter
+									Property="Fill"
+									Value="{Binding InactiveBrush}" />
+                            </DataTrigger>
+                            <DataTrigger
+								Value="True"
+								Binding="{Binding IsBlinking}">
+                                <Setter
+									Property="Fill"
+									Value="{Binding ActiveBrush}" />
+                                <TriggerBase.EnterActions>
+                                    <BeginStoryboard
+										Name="BlinkingStoryboard"
+										Storyboard="{StaticResource Storyboard.Blinking}" />
+                                </TriggerBase.EnterActions>
+                            </DataTrigger>
+                            <DataTrigger
+								Value="False"
+								Binding="{Binding IsBlinking}">
+                                <TriggerBase.EnterActions>
+                                    <StopStoryboard
+										BeginStoryboardName="BlinkingStoryboard" />
+                                </TriggerBase.EnterActions>
+                                <Setter
+									Property="UIElement.Opacity"
+									Value="1" />
+                            </DataTrigger>
+                        </Style.Triggers>
+                    </Style>
+                </FrameworkElement.Style>
+            </Ellipse>
+            <Ellipse
+				Grid.Column="1"
+				Width="12"
+				Height="12"
+				Margin="4,0,0,0">
+                <FrameworkElement.Style>
+                    <Style
+						TargetType="{x:Type Ellipse}">
+                        <Style.Triggers>
+                            <DataTrigger
+								Binding="{Binding IsSecondStatusActive}"
+								Value="{x:Null}">
+                                <Setter
+									Property="Visibility"
+									Value="Collapsed" />
+                            </DataTrigger>
+                            <DataTrigger
+								Value="True"
+								Binding="{Binding IsSecondStatusActive}">
+                                <Setter
+									Property="Fill"
+									Value="{Binding ActiveBrush}" />
+                            </DataTrigger>
+                            <DataTrigger
+								Value="False"
+								Binding="{Binding IsSecondStatusActive}">
+                                <Setter
+									Property="Fill"
+									Value="{Binding InactiveBrush}" />
+                            </DataTrigger>
+                            <DataTrigger
+								Value="True"
+								Binding="{Binding IsSecondStatusBlinking}">
+                                <Setter
+									Property="Fill"
+									Value="{Binding ActiveBrush}" />
+                                <TriggerBase.EnterActions>
+                                    <BeginStoryboard
+										Name="BlinkingStoryboard"
+										Storyboard="{StaticResource Storyboard.Blinking}" />
+                                </TriggerBase.EnterActions>
+                            </DataTrigger>
+                            <DataTrigger
+								Value="False"
+								Binding="{Binding IsSecondStatusBlinking}">
+                                <TriggerBase.EnterActions>
+                                    <StopStoryboard
+										BeginStoryboardName="BlinkingStoryboard" />
+                                </TriggerBase.EnterActions>
+                                <Setter
+									Property="UIElement.Opacity"
+									Value="1" />
+                            </DataTrigger>
+                        </Style.Triggers>
+                    </Style>
+                </FrameworkElement.Style>
+            </Ellipse>
+            <TextBlock
+				Grid.Column="2"
+				Margin="8,0"
+				Padding="0"
+				VerticalAlignment="Center"
+				FontFamily="{StaticResource FontFamily.Global}"
+				Foreground="{StaticResource Brush.Text}"
+				Text="{Binding Label}" />
+        </Grid>
+        <FrameworkElement.Style>
+            <Style
+				TargetType="{x:Type Border}">
+                <Setter
+					Property="BorderThickness"
+					Value="1" />
+                <Style.Triggers>
+                    <DataTrigger
+						Value="false"
+						Binding="{Binding IsBorderVisible}">
+                        <Setter
+							Property="BorderThickness"
+							Value="0" />
+                    </DataTrigger>
+                </Style.Triggers>
+            </Style>
+        </FrameworkElement.Style>
+    </Border>
+</UserControl>

+ 156 - 0
SKMC.UI/UserControls/StatusControl.xaml.cs

@@ -0,0 +1,156 @@
+using SKMC.UI.CustomControls;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace SKMC.UI.UserControls
+{
+    /// <summary>
+    /// StatusControl.xaml 的交互逻辑
+    /// </summary>
+    public partial class StatusControl : UserControl
+    {
+        public SolidColorBrush ActiveBrush
+        {
+            get
+            {
+                return (SolidColorBrush)base.GetValue(StatusControl.ActiveBrushProperty);
+            }
+            set
+            {
+                base.SetValue(StatusControl.ActiveBrushProperty, value);
+            }
+        }
+
+        public SolidColorBrush InactiveBrush
+        {
+            get
+            {
+                return (SolidColorBrush)base.GetValue(StatusControl.InactiveBrushProperty);
+            }
+            set
+            {
+                base.SetValue(StatusControl.InactiveBrushProperty, value);
+            }
+        }
+
+        public string Label
+        {
+            get
+            {
+                return (string)base.GetValue(StatusControl.LabelProperty);
+            }
+            set
+            {
+                base.SetValue(StatusControl.LabelProperty, value);
+            }
+        }
+
+        public bool IsActive
+        {
+            get
+            {
+                return (bool)base.GetValue(StatusControl.IsActiveProperty);
+            }
+            set
+            {
+                base.SetValue(StatusControl.IsActiveProperty, value);
+            }
+        }
+        /// <summary>
+        /// 是否闪烁
+        /// </summary>
+        public bool IsBlinking
+        {
+            get
+            {
+                return (bool)base.GetValue(StatusControl.IsBlinkingProperty);
+            }
+            set
+            {
+                base.SetValue(StatusControl.IsBlinkingProperty, value);
+            }
+        }
+        /// <summary>
+        /// 第二状态是否激活
+        /// </summary>
+        public bool? IsSecondStatusActive
+        {
+            get
+            {
+                return (bool?)base.GetValue(StatusControl.IsSecondStatusActiveProperty);
+            }
+            set
+            {
+                base.SetValue(StatusControl.IsSecondStatusActiveProperty, value);
+            }
+        }
+        /// <summary>
+        /// 第二状态是否闪烁
+        /// </summary>
+        public bool IsSecondStatusBlinking
+        {
+            get
+            {
+                return (bool)base.GetValue(StatusControl.IsSecondStatusBlinkingProperty);
+            }
+            set
+            {
+                base.SetValue(StatusControl.IsSecondStatusBlinkingProperty, value);
+            }
+        }
+        /// <summary>
+        /// 边框是否可见
+        /// </summary>
+        public bool IsBorderVisible
+        {
+            get
+            {
+                return (bool)base.GetValue(StatusControl.IsBorderVisibleProperty);
+            }
+            set
+            {
+                base.SetValue(StatusControl.IsBorderVisibleProperty, value);
+            }
+        }
+        public CornerRadius CornerRadius
+        {
+            get { return (CornerRadius)GetValue(CornerRadiusProperty); }
+            set { SetValue(CornerRadiusProperty, value); }
+        }
+
+        public StatusControl()
+        {
+            InitializeComponent();
+        }
+        public static readonly DependencyProperty ActiveBrushProperty = DependencyProperty.Register("ActiveBrush", typeof(SolidColorBrush), typeof(StatusControl), new PropertyMetadata(new BrushConverter().ConvertFromString("#00F976")));
+
+        public static readonly DependencyProperty InactiveBrushProperty = DependencyProperty.Register("InactiveBrush", typeof(SolidColorBrush), typeof(StatusControl), new PropertyMetadata(new BrushConverter().ConvertFromString("#404040")));
+
+        public static readonly DependencyProperty LabelProperty = DependencyProperty.Register("Label", typeof(string), typeof(StatusControl));
+
+        public static readonly DependencyProperty IsActiveProperty = DependencyProperty.Register("IsActive", typeof(bool), typeof(StatusControl));
+
+        public static readonly DependencyProperty IsBlinkingProperty = DependencyProperty.Register("IsBlinking", typeof(bool), typeof(StatusControl));
+
+        public static readonly DependencyProperty IsSecondStatusActiveProperty = DependencyProperty.Register("IsSecondStatusActive", typeof(bool?), typeof(StatusControl));
+
+        public static readonly DependencyProperty IsSecondStatusBlinkingProperty = DependencyProperty.Register("IsSecondStatusBlinking", typeof(bool), typeof(StatusControl));
+
+        public static readonly DependencyProperty IsBorderVisibleProperty = DependencyProperty.Register("IsBorderVisible", typeof(bool), typeof(StatusControl), new PropertyMetadata(true));
+        public static readonly DependencyProperty CornerRadiusProperty =
+            DependencyProperty.Register(nameof(CornerRadius), typeof(CornerRadius), typeof(StatusControl), new PropertyMetadata(new CornerRadius(0, 0, 0, 0)));
+
+    }
+}

+ 63 - 0
SKMC.UI/UserControls/WaitIconControl.xaml

@@ -0,0 +1,63 @@
+<UserControl x:Class="SKMC.UI.UserControls.WaitIconControl"
+             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:SKMC.UI.UserControls"
+             mc:Ignorable="d" 
+             d:DesignHeight="450" d:DesignWidth="800"
+             Name="parent">
+    <FrameworkElement.Resources>
+        <ResourceDictionary>
+            <Storyboard
+				DesiredFrameRate="24"
+				x:Key="SpinnerStoryboard">
+                <DoubleAnimation
+					RepeatBehavior="Forever"
+					Storyboard.TargetProperty="(Path.RenderTransform).(RotateTransform.Angle)"
+					To="360"
+					Duration="0:0:1" />
+            </Storyboard>
+        </ResourceDictionary>
+    </FrameworkElement.Resources>
+    <Border
+		Background="{Binding Background}"
+		DataContext="{Binding ElementName=parent}"
+		Visibility="{Binding ShowWait, Converter={StaticResource BooleanToCollapsedConverter}}">
+        <Path
+			Margin="0"
+			Data="{StaticResource Icon.Spinner}"
+			Stretch="Uniform"
+			Fill="{Binding SpinnerColor}">
+            <UIElement.RenderTransform>
+                <RotateTransform
+					Angle="0" />
+            </UIElement.RenderTransform>
+            <UIElement.RenderTransformOrigin>
+                <Point
+					X="0.5"
+					Y="0.5" />
+            </UIElement.RenderTransformOrigin>
+            <FrameworkElement.Style>
+                <Style
+					TargetType="{x:Type Path}">
+                    <Style.Triggers>
+                        <DataTrigger
+							Value="True"
+							Binding="{Binding ShowWait}">
+                            <TriggerBase.EnterActions>
+                                <BeginStoryboard
+									Name="Storyboard"
+									Storyboard="{StaticResource SpinnerStoryboard}" />
+                            </TriggerBase.EnterActions>
+                            <TriggerBase.ExitActions>
+                                <StopStoryboard
+									BeginStoryboardName="Storyboard" />
+                            </TriggerBase.ExitActions>
+                        </DataTrigger>
+                    </Style.Triggers>
+                </Style>
+            </FrameworkElement.Style>
+        </Path>
+    </Border>
+</UserControl>

+ 56 - 0
SKMC.UI/UserControls/WaitIconControl.xaml.cs

@@ -0,0 +1,56 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace SKMC.UI.UserControls
+{
+    /// <summary>
+    /// WaitIconControl.xaml 的交互逻辑
+    /// </summary>
+    public partial class WaitIconControl : UserControl
+    {
+        public bool ShowWait
+        {
+            get
+            {
+                return (bool)base.GetValue(ShowWaitProperty);
+            }
+            set
+            {
+                base.SetValue(ShowWaitProperty, value);
+            }
+        }
+        /// <summary>
+        /// 旋转颜色
+        /// </summary>
+        public SolidColorBrush SpinnerColor
+        {
+            get
+            {
+                return (SolidColorBrush)base.GetValue(SpinnerColorProperty);
+            }
+            set
+            {
+                base.SetValue(SpinnerColorProperty, value);
+            }
+        }
+        public WaitIconControl()
+        {
+            InitializeComponent();
+        }
+        public static readonly DependencyProperty ShowWaitProperty = DependencyProperty.Register("ShowWait", typeof(bool), typeof(WaitIconControl), new PropertyMetadata(false));
+
+        public static readonly DependencyProperty SpinnerColorProperty = DependencyProperty.Register("SpinnerColor", typeof(SolidColorBrush), typeof(WaitIconControl), new PropertyMetadata(new BrushConverter().ConvertFromString("#00FF00")));
+    }
+}

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно