WPF自定义控件
控件模板
顾名思义就是在原有的控件上进行模版修改成自己需要的样式
把ProgressBar修改为一个水液面的进度条
<Window x:Class="XH.CustomLesson.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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:local="clr-namespace:XH.CustomLesson"mc:Ignorable="d"Title="MainWindow" Height="450" Width="800"><Window.Resources><SolidColorBrush x:Key="ProgressBar.Progress" Color="#FF06B025"/><SolidColorBrush x:Key="ProgressBar.Background" Color="#FFE6E6E6"/><SolidColorBrush x:Key="ProgressBar.Border" Color="#FFBCBCBC"/><Style x:Key="ProgressBarStyle" TargetType="{x:Type ProgressBar}"><Setter Property="Foreground" Value="{StaticResource ProgressBar.Progress}"/><Setter Property="Background" Value="{StaticResource ProgressBar.Background}"/><Setter Property="BorderBrush" Value="{StaticResource ProgressBar.Border}"/><Setter Property="BorderThickness" Value="1"/><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type ProgressBar}"><Grid x:Name="TemplateRoot"><VisualStateManager.VisualStateGroups><VisualStateGroup x:Name="CommonStates"><VisualState x:Name="Determinate"/><VisualState x:Name="Indeterminate"><Storyboard RepeatBehavior="Forever"><DoubleAnimationUsingKeyFrames Storyboard.TargetName="Animation" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)"><EasingDoubleKeyFrame KeyTime="0" Value="0.25"/><EasingDoubleKeyFrame KeyTime="0:0:1" Value="0.25"/><EasingDoubleKeyFrame KeyTime="0:0:2" Value="0.25"/></DoubleAnimationUsingKeyFrames><PointAnimationUsingKeyFrames Storyboard.TargetName="Animation" Storyboard.TargetProperty="(UIElement.RenderTransformOrigin)"><EasingPointKeyFrame KeyTime="0" Value="-0.5,0.5"/><EasingPointKeyFrame KeyTime="0:0:1" Value="0.5,0.5"/><EasingPointKeyFrame KeyTime="0:0:2" Value="1.5,0.5"/></PointAnimationUsingKeyFrames></Storyboard></VisualState></VisualStateGroup></VisualStateManager.VisualStateGroups><Border Background="{TemplateBinding Background}"BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"CornerRadius="5"/><Rectangle x:Name="PART_Track"/><Grid x:Name="PART_Indicator" ClipToBounds="True" HorizontalAlignment="Left"><Border x:Name="Indicator" Background="Transparent"><Canvas><Canvas.LayoutTransform><RotateTransform Angle="90" /></Canvas.LayoutTransform><Path Data="M0 0A70 70 0 0 0 50 0A70 70 0 0 1 100 0L 100 100 0 100" Fill="Orange"><Path.RenderTransform><TranslateTransform X="-30" x:Name="tt" /></Path.RenderTransform></Path><Path Data="M0 0A70 70 0 0 0 50 0A70 70 0 0 1 100 0L 100 100 0 100" Fill="#9f90"><Path.RenderTransform><TranslateTransform X="0" x:Name="tt_2" /></Path.RenderTransform></Path><Path Data="M0 0A70 70 0 0 0 50 0A70 70 0 0 1 100 0L100 100 0 100" Fill="#9f80"><Path.RenderTransform><TranslateTransform X="-50" x:Name="tt_3" /></Path.RenderTransform></Path></Canvas></Border></Grid></Grid><ControlTemplate.Triggers><Trigger Property="Orientation" Value="Vertical"><Setter Property="LayoutTransform" TargetName="TemplateRoot"><Setter.Value><RotateTransform Angle="-90"/></Setter.Value></Setter></Trigger><Trigger Property="IsIndeterminate" Value="true"><Setter Property="Visibility" TargetName="Indicator" Value="Collapsed"/></Trigger><EventTrigger RoutedEvent="Loaded"><BeginStoryboard><Storyboard><DoubleAnimation RepeatBehavior="Forever" Duration="0:0:1" From="0" To="-50" Storyboard.TargetName="tt" Storyboard.TargetProperty="X"/><DoubleAnimation RepeatBehavior="Forever" BeginTime="0:0:0.3" Duration="0:0:1.3" From="0" To="-50" Storyboard.TargetName="tt_2" Storyboard.TargetProperty="X"/><DoubleAnimation RepeatBehavior="Forever" BeginTime="0:0:0.6" Duration="0:0:1.6" From="-50" To="0" Storyboard.TargetName="tt_3" Storyboard.TargetProperty="X"/></Storyboard></BeginStoryboard></EventTrigger></ControlTemplate.Triggers></ControlTemplate></Setter.Value></Setter></Style></Window.Resources><Grid><ProgressBar Style="{DynamicResource ProgressBarStyle}"BorderThickness="0"Height="200" Width="50" Orientation="Vertical" Value="450" Maximum="750" Minimum="0"/></Grid>
</Window>
想要弧度更大,修改对应的path即可:
UserControl 用户控件
案例:日期时间选择器 DatePicker
XAML代码:
<UserControl x:Class="XH.CustomLesson.Controls.DateTimePicker"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:XH.CustomLesson.Controls"mc:Ignorable="d" d:DesignHeight="30" d:DesignWidth="200"><UserControl.Resources><Style TargetType="RepeatButton" x:Key="ButtonUpStyle"><Setter Property="Height" Value="18"/><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="RepeatButton"><Border Background="Transparent"><Path Data="M838.116 732.779 877.7 693.195 511.979 327.549 146.3 693.195 185.883 732.779 512.003 406.652Z"Fill="#999" Stretch="Uniform" Margin="6"/></Border></ControlTemplate></Setter.Value></Setter></Style><Style TargetType="RepeatButton" x:Key="ButtonDownStyle"><Setter Property="Height" Value="18"/><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="RepeatButton"><Border Background="Transparent"><Path Data="M185.884 327.55 146.3 367.133 512.021 732.779 877.7 367.133 838.117 327.55 511.997 653.676Z"Fill="#999" Stretch="Uniform" Margin="6"/></Border></ControlTemplate></Setter.Value></Setter></Style><Style TargetType="Button" x:Key="ButtonCancelStyle"><Setter Property="Width" Value="24"/><Setter Property="Height" Value="24"/><Setter Property="HorizontalAlignment" Value="Right"/><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="Button"><Border Background="#EEE"><Path Data="M557.3 512l329.3-329.4a32 32 0 1 0-45.2-45.2L512 466.7 182.6 137.4a32 32 0 1 0-45.2 45.2L466.7 512 137.4 841.4a31.9 31.9 0 0 0 0 45.2 31.9 31.9 0 0 0 45.2 0L512 557.3l329.4 329.3a31.9 31.9 0 0 0 45.2 0 31.9 31.9 0 0 0 0-45.2z"Fill="#999" Stretch="Uniform" HorizontalAlignment="Center" Margin="5"/></Border></ControlTemplate></Setter.Value></Setter></Style><Style TargetType="Button" x:Key="ButtonAcceptStyle"><Setter Property="Width" Value="24"/><Setter Property="Height" Value="24"/><Setter Property="HorizontalAlignment" Value="Right"/><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="Button"><Border Background="#EEE"><Path Data="M892.064 261.888a31.936 31.936 0 0 0-45.216 1.472L421.664 717.248l-220.448-185.216a32 32 0 1 0-41.152 48.992l243.648 204.704a31.872 31.872 0 0 0 20.576 7.488 31.808 31.808 0 0 0 23.36-10.112L893.536 307.136a32 32 0 0 0-1.472-45.248z"Fill="#999" Stretch="Uniform" HorizontalAlignment="Center" Margin="5"/></Border></ControlTemplate></Setter.Value></Setter></Style><Style x:Key="CalendarCalendarDayButtonStyle1" TargetType="{x:Type CalendarDayButton}"><Setter Property="MinWidth" Value="10"/><Setter Property="MinHeight" Value="10"/><Setter Property="FontSize" Value="13"/><Setter Property="HorizontalContentAlignment" Value="Center"/><Setter Property="VerticalContentAlignment" Value="Center"/><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type CalendarDayButton}"><Grid><VisualStateManager.VisualStateGroups><VisualStateGroup x:Name="CommonStates"><VisualStateGroup.Transitions><VisualTransition GeneratedDuration="0:0:0.1"/></VisualStateGroup.Transitions><VisualState x:Name="Normal"/><VisualState x:Name="MouseOver"><Storyboard><DoubleAnimation Duration="0" Storyboard.TargetName="HighlightBackground" To="0.5" Storyboard.TargetProperty="Opacity"/></Storyboard></VisualState><VisualState x:Name="Pressed"><Storyboard><DoubleAnimation Duration="0" Storyboard.TargetName="HighlightBackground" To="0.5" Storyboard.TargetProperty="Opacity"/></Storyboard></VisualState><VisualState x:Name="Disabled"><Storyboard><DoubleAnimation Duration="0" Storyboard.TargetName="HighlightBackground" To="0" Storyboard.TargetProperty="Opacity"/><DoubleAnimation Duration="0" Storyboard.TargetName="NormalText" To=".35" Storyboard.TargetProperty="Opacity"/></Storyboard></VisualState></VisualStateGroup><VisualStateGroup x:Name="SelectionStates"><VisualStateGroup.Transitions><VisualTransition GeneratedDuration="0"/></VisualStateGroup.Transitions><VisualState x:Name="Unselected"/><VisualState x:Name="Selected"><Storyboard><DoubleAnimation Duration="0" Storyboard.TargetName="SelectedBackground" To=".75" Storyboard.TargetProperty="Opacity"/><ColorAnimation Duration="0" Storyboard.TargetName="NormalText" To="#FFFFFFFF" Storyboard.TargetProperty="(TextElement.Foreground).(SolidColorBrush.Color)"/></Storyboard></VisualState></VisualStateGroup><VisualStateGroup x:Name="CalendarButtonFocusStates"><VisualStateGroup.Transitions><VisualTransition GeneratedDuration="0"/></VisualStateGroup.Transitions><VisualState x:Name="CalendarButtonFocused"><Storyboard><ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetName="DayButtonFocusVisual" Storyboard.TargetProperty="Visibility"><DiscreteObjectKeyFrame KeyTime="0"><DiscreteObjectKeyFrame.Value><Visibility>Visible</Visibility></DiscreteObjectKeyFrame.Value></DiscreteObjectKeyFrame></ObjectAnimationUsingKeyFrames></Storyboard></VisualState><VisualState x:Name="CalendarButtonUnfocused"><Storyboard><ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetName="DayButtonFocusVisual" Storyboard.TargetProperty="Visibility"><DiscreteObjectKeyFrame KeyTime="0"><DiscreteObjectKeyFrame.Value><Visibility>Collapsed</Visibility></DiscreteObjectKeyFrame.Value></DiscreteObjectKeyFrame></ObjectAnimationUsingKeyFrames></Storyboard></VisualState></VisualStateGroup><VisualStateGroup x:Name="ActiveStates"><VisualStateGroup.Transitions><VisualTransition GeneratedDuration="0"/></VisualStateGroup.Transitions><VisualState x:Name="Active"/><VisualState x:Name="Inactive"><Storyboard><ColorAnimation Duration="0" Storyboard.TargetName="NormalText" To="#FF777777" Storyboard.TargetProperty="(TextElement.Foreground).(SolidColorBrush.Color)"/></Storyboard></VisualState></VisualStateGroup><VisualStateGroup x:Name="DayStates"><VisualStateGroup.Transitions><VisualTransition GeneratedDuration="0"/></VisualStateGroup.Transitions><VisualState x:Name="RegularDay"/><VisualState x:Name="Today"><Storyboard><DoubleAnimation Duration="0" Storyboard.TargetName="TodayBackground" To="1" Storyboard.TargetProperty="Opacity"/><ColorAnimation Duration="0" Storyboard.TargetName="NormalText" To="#FFFFFFFF" Storyboard.TargetProperty="(TextElement.Foreground).(SolidColorBrush.Color)"/></Storyboard></VisualState></VisualStateGroup><VisualStateGroup x:Name="BlackoutDayStates"><VisualStateGroup.Transitions><VisualTransition GeneratedDuration="0"/></VisualStateGroup.Transitions><VisualState x:Name="NormalDay"/><VisualState x:Name="BlackoutDay"><Storyboard><DoubleAnimation Duration="0" Storyboard.TargetName="Blackout" To=".2" Storyboard.TargetProperty="Opacity"/></Storyboard></VisualState></VisualStateGroup></VisualStateManager.VisualStateGroups><Rectangle x:Name="TodayBackground" Fill="Gray" Opacity="0" RadiusX="1" RadiusY="1"/><Rectangle x:Name="SelectedBackground" Fill="#409EFE" Opacity="0" RadiusX="1" RadiusY="1"/><Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"/><Rectangle x:Name="HighlightBackground" Fill="#FFBADDE9" Opacity="0" RadiusX="1" RadiusY="1"/><ContentPresenter x:Name="NormalText" TextElement.Foreground="#FF333333" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="5,1,5,1" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/><Path x:Name="Blackout" Data="M8.1772461,11.029181 L10.433105,11.029181 L11.700684,12.801641 L12.973633,11.029181 L15.191895,11.029181 L12.844727,13.999395 L15.21875,17.060919 L12.962891,17.060919 L11.673828,15.256231 L10.352539,17.060919 L8.1396484,17.060919 L10.519043,14.042364 z" Fill="#FF000000" HorizontalAlignment="Stretch" Margin="3" Opacity="0" RenderTransformOrigin="0.5,0.5" Stretch="Fill" VerticalAlignment="Stretch"/><Rectangle x:Name="DayButtonFocusVisual" IsHitTestVisible="false" RadiusX="1" RadiusY="1" Stroke="#FF45D6FA" Visibility="Collapsed"/></Grid></ControlTemplate></Setter.Value></Setter></Style><Style x:Key="CalendarCalendarItemStyle1" TargetType="{x:Type CalendarItem}"><Setter Property="Margin" Value="0,3,0,3"/><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type CalendarItem}"><ControlTemplate.Resources><DataTemplate x:Key="{x:Static CalendarItem.DayTitleTemplateResourceKey}"><TextBlock Foreground="#FF333333" FontFamily="Verdana" FontWeight="Bold" FontSize="9.5" HorizontalAlignment="Center" Margin="0,6,0,6" Text="{Binding}" VerticalAlignment="Center"/></DataTemplate></ControlTemplate.Resources><Grid x:Name="PART_Root"><Grid.Resources><SolidColorBrush x:Key="DisabledColor" Color="#A5FFFFFF"/></Grid.Resources><VisualStateManager.VisualStateGroups><VisualStateGroup x:Name="CommonStates"><VisualState x:Name="Normal"/><VisualState x:Name="Disabled"><Storyboard><DoubleAnimation Duration="0" Storyboard.TargetName="PART_DisabledVisual" To="1" Storyboard.TargetProperty="Opacity"/></Storyboard></VisualState></VisualStateGroup></VisualStateManager.VisualStateGroups><Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="1"><Border BorderBrush="#FFFFFFFF" BorderThickness="0" CornerRadius="1"><Grid><Grid.Resources><ControlTemplate x:Key="PreviousButtonTemplate" TargetType="{x:Type Button}"><Grid Cursor="Hand"><VisualStateManager.VisualStateGroups><VisualStateGroup x:Name="CommonStates"><VisualState x:Name="Normal"/><VisualState x:Name="MouseOver"><Storyboard><ColorAnimation Duration="0" Storyboard.TargetName="path" To="#FF73A9D8" Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)"/></Storyboard></VisualState><VisualState x:Name="Disabled"><Storyboard><DoubleAnimation Duration="0" Storyboard.TargetName="path" To=".5" Storyboard.TargetProperty="(Shape.Fill).(Brush.Opacity)"/></Storyboard></VisualState></VisualStateGroup></VisualStateManager.VisualStateGroups><Grid Background="Transparent"><Path x:Name="path" Data="M671.968176 911.99957c-12.287381 0-24.576482-4.67206-33.951566-14.047144L286.048434 545.984249c-18.751888-18.719204-18.751888-49.12028 0-67.872168L638.016611 126.111222c18.751888-18.751888 49.12028-18.751888 67.872168 0 18.751888 18.719204 18.751888 49.12028 0 67.872168l-318.016611 318.047574L705.888778 830.047574c18.751888 18.751888 18.751888 49.12028 0 67.872168C696.544658 907.32751 684.255557 911.99957 671.968176 911.99957z" Fill="#FF333333" HorizontalAlignment="Center" VerticalAlignment="Center"Height="10" Width="6" Stretch="Fill" Margin="10,0"/></Grid></Grid></ControlTemplate><ControlTemplate x:Key="NextButtonTemplate" TargetType="{x:Type Button}"><Grid Cursor="Hand"><VisualStateManager.VisualStateGroups><VisualStateGroup x:Name="CommonStates"><VisualState x:Name="Normal"/><VisualState x:Name="MouseOver"><Storyboard><ColorAnimation Duration="0" Storyboard.TargetName="path" To="#FF73A9D8" Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)"/></Storyboard></VisualState><VisualState x:Name="Disabled"><Storyboard><DoubleAnimation Duration="0" Storyboard.TargetName="path" To=".5" Storyboard.TargetProperty="(Shape.Fill).(Brush.Opacity)"/></Storyboard></VisualState></VisualStateGroup></VisualStateManager.VisualStateGroups><Grid Background="Transparent"><Path x:Name="path" Data="M761.055557 532.128047c0.512619-0.992555 1.343475-1.823411 1.792447-2.848649 8.800538-18.304636 5.919204-40.703346-9.664077-55.424808L399.935923 139.743798c-19.264507-18.208305-49.631179-17.344765-67.872168 1.888778-18.208305 19.264507-17.375729 49.631179 1.888778 67.872168l316.960409 299.839269L335.199677 813.631716c-19.071845 18.399247-19.648112 48.767639-1.247144 67.872168 9.407768 9.791372 21.984142 14.688778 34.560516 14.688778 12.000108 0 24.000215-4.479398 33.311652-13.439914l350.048434-337.375729c0.672598-0.672598 0.927187-1.599785 1.599785-2.303346 0.512619-0.479935 1.056202-0.832576 1.567101-1.343475C757.759656 538.879828 759.199462 535.391265 761.055557 532.128047z" Fill="#FF333333" HorizontalAlignment="Right" VerticalAlignment="Center" Height="10" Stretch="Fill" Width="6" Margin="10,0"/></Grid></Grid></ControlTemplate><ControlTemplate x:Key="HeaderButtonTemplate" TargetType="{x:Type Button}"><Grid Cursor="Hand" Background="Transparent"><VisualStateManager.VisualStateGroups><VisualStateGroup x:Name="CommonStates"><VisualState x:Name="Normal"/><VisualState x:Name="MouseOver"><Storyboard><ColorAnimation Duration="0" Storyboard.TargetName="buttonContent" To="#FF73A9D8" Storyboard.TargetProperty="(TextElement.Foreground).(SolidColorBrush.Color)"/></Storyboard></VisualState><VisualState x:Name="Disabled"><Storyboard><DoubleAnimation Duration="0" Storyboard.TargetName="buttonContent" To=".5" Storyboard.TargetProperty="Opacity"/></Storyboard></VisualState></VisualStateGroup></VisualStateManager.VisualStateGroups><ContentPresenter x:Name="buttonContent" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" TextElement.Foreground="#FF333333"HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="1,9" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/></Grid></ControlTemplate></Grid.Resources><Grid.ColumnDefinitions><ColumnDefinition Width="*"/><ColumnDefinition Width="auto"/><ColumnDefinition Width="auto"/></Grid.ColumnDefinitions><Grid.RowDefinitions><RowDefinition Height="Auto"/><RowDefinition Height="*"/></Grid.RowDefinitions><Button x:Name="PART_HeaderButton" Grid.Column="0" Focusable="False" FontWeight="Bold" FontSize="14" HorizontalAlignment="Left" VerticalContentAlignment="Center"Grid.Row="0" Template="{StaticResource HeaderButtonTemplate}" VerticalAlignment="Center" Margin="10,5"/><Button x:Name="PART_PreviousButton" Grid.Column="1" Focusable="False" HorizontalAlignment="Center" Template="{StaticResource PreviousButtonTemplate}" Margin="0,5"/><Button x:Name="PART_NextButton" Grid.Column="2" Focusable="False" HorizontalAlignment="Right" Template="{StaticResource NextButtonTemplate}" Margin="0,5"/><Grid x:Name="PART_MonthView" Grid.ColumnSpan="3" HorizontalAlignment="Center" Margin="6,-1,6,6" Grid.Row="1" Visibility="Visible"><Grid.ColumnDefinitions><ColumnDefinition Width="30"/><ColumnDefinition Width="30"/><ColumnDefinition Width="30"/><ColumnDefinition Width="30"/><ColumnDefinition Width="30"/><ColumnDefinition Width="30"/><ColumnDefinition Width="30"/></Grid.ColumnDefinitions><Grid.RowDefinitions><RowDefinition Height="Auto"/><RowDefinition Height="30"/><RowDefinition Height="30"/><RowDefinition Height="30"/><RowDefinition Height="30"/><RowDefinition Height="30"/><RowDefinition Height="30"/></Grid.RowDefinitions></Grid><Grid x:Name="PART_YearView" Grid.ColumnSpan="3" HorizontalAlignment="Center" Margin="6,-3,7,6" Grid.Row="1" Visibility="Hidden"><Grid.ColumnDefinitions><ColumnDefinition Width="50"/><ColumnDefinition Width="50"/><ColumnDefinition Width="50"/><ColumnDefinition Width="50"/></Grid.ColumnDefinitions><Grid.RowDefinitions><RowDefinition Height="50"/><RowDefinition Height="50"/><RowDefinition Height="50"/></Grid.RowDefinitions></Grid></Grid></Border></Border><Rectangle x:Name="PART_DisabledVisual" Fill="{StaticResource DisabledColor}" Opacity="0" RadiusX="2" RadiusY="2" Stroke="{StaticResource DisabledColor}" Stretch="Fill" StrokeThickness="1" Visibility="Collapsed"/></Grid><ControlTemplate.Triggers><Trigger Property="IsEnabled" Value="False"><Setter Property="Visibility" TargetName="PART_DisabledVisual" Value="Visible"/></Trigger><DataTrigger Binding="{Binding DisplayMode, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Calendar}}}" Value="Year"><Setter Property="Visibility" TargetName="PART_MonthView" Value="Hidden"/><Setter Property="Visibility" TargetName="PART_YearView" Value="Visible"/></DataTrigger><DataTrigger Binding="{Binding DisplayMode, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Calendar}}}" Value="Decade"><Setter Property="Visibility" TargetName="PART_MonthView" Value="Hidden"/><Setter Property="Visibility" TargetName="PART_YearView" Value="Visible"/></DataTrigger></ControlTemplate.Triggers></ControlTemplate></Setter.Value></Setter></Style></UserControl.Resources><Grid><Grid.ColumnDefinitions><ColumnDefinition /><ColumnDefinition Width="30" /></Grid.ColumnDefinitions><TextBox Grid.Column="0" IsReadOnly="True" Name="textBox" VerticalContentAlignment="Center"Text="{Binding CurrentDateTime,RelativeSource={RelativeSource AncestorType=UserControl},StringFormat={}{0:yyyy-MM-dd HH:mm:ss}}"/><ToggleButton Grid.Column="1" x:Name="toggleButton" Background="AliceBlue"><ToggleButton.Content><local:DateTimePickerIcon /></ToggleButton.Content></ToggleButton><!--AllowsTransparency:控件包含透明内容--><Popup StaysOpen="False" IsOpen="{Binding ElementName=toggleButton,Path=IsChecked}" PlacementTarget="{Binding ElementName=textBox}" AllowsTransparency="True"HorizontalOffset="0" Name="popup"><Border Background="#F7F9FA" Width="auto" Height="auto" Margin="3"><Border.Effect><DropShadowEffect BlurRadius="10" Color="Gray" ShadowDepth="0" Opacity="0.3" /></Border.Effect><Grid><Grid.RowDefinitions><RowDefinition Height="auto"/><RowDefinition Height="auto"/></Grid.RowDefinitions><Calendar x:Name="calendar" BorderThickness="0"Background="Transparent"CalendarItemStyle="{StaticResource CalendarCalendarItemStyle1}" CalendarDayButtonStyle="{StaticResource CalendarCalendarDayButtonStyle1}"/><Grid Grid.Row="1" Margin="10,5,10,10"><Grid.RowDefinitions><RowDefinition/><RowDefinition Height="30"/><RowDefinition/></Grid.RowDefinitions><Grid.ColumnDefinitions><ColumnDefinition/><ColumnDefinition Width="auto"/><ColumnDefinition/><ColumnDefinition Width="auto"/><ColumnDefinition/><ColumnDefinition/><ColumnDefinition/></Grid.ColumnDefinitions><RepeatButton Content="△" Style="{StaticResource ButtonUpStyle}" Click="BtnHourUp_Click"/><RepeatButton Content="△" Style="{StaticResource ButtonUpStyle}" Grid.Column="2" Click="BtnMinuteUp_Click"/><RepeatButton Content="△" Style="{StaticResource ButtonUpStyle}" Grid.Column="4" Click="BtnSecondUp_Click"/><RepeatButton Content="▽" Style="{StaticResource ButtonDownStyle}" Grid.Row="2" Click="BtnHourDown_Click"/><RepeatButton Content="▽" Style="{StaticResource ButtonDownStyle}" Grid.Row="2" Grid.Column="2" Click="BtnMinuteDown_Click"/><RepeatButton Content="▽" Style="{StaticResource ButtonDownStyle}" Grid.Row="2" Grid.Column="4" Click="BtnSecondDown_Click"/><TextBox Grid.Row="1" Name="tb_hour" TextChanged="tb_hour_TextChanged" Text="{Binding HourInt,RelativeSource={RelativeSource AncestorType=UserControl}}" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" Height="24" Margin="3"/><TextBlock Text=":" Grid.Row="1" Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="3"/><TextBox Grid.Row="1" Grid.Column="2" Name="tb_minute" TextChanged="tb_minute_TextChanged" Text="{Binding MinuteInt,RelativeSource={RelativeSource AncestorType=UserControl}}" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" Height="24" Margin="3"/><TextBlock Text=":" Grid.Row="1" Grid.Column="3" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="3"/><TextBox Grid.Row="1" Grid.Column="4" Name="tb_second" TextChanged="tb_second_TextChanged" Text="{Binding SecondInt,RelativeSource={RelativeSource AncestorType=UserControl}}"VerticalContentAlignment="Center" HorizontalContentAlignment="Center" Height="24" Margin="3"/><Button Content="×" Style="{StaticResource ButtonCancelStyle}" Click="Button_Click_1" BorderThickness="0" Grid.Row="1" Grid.Column="5" /><Button Content="√" Style="{StaticResource ButtonAcceptStyle}" BorderThickness="0" Grid.Row="1" Grid.Column="6" Click="Button_Click"/></Grid></Grid></Border></Popup></Grid>
</UserControl>
图标XAML:
<UserControl x:Class="XH.CustomLesson.Controls.DateTimePickerIcon"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:XH.CustomLesson.Controls"mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800"><Viewbox><Grid><Path Data="M47.93344 167.1936h-0.98816v248.83712h933.248V355.31264c0.04096-1.00352 0.29696-1.9456 0.29696-2.95936V177.00864c0-1.01376-0.256-1.95584-0.29696-2.95936v-6.85568h-0.6912c-4.80256-33.50016-33.3312-59.3408-68.16256-59.3408H116.096c-34.82624 0.00512-63.36 25.84064-68.16256 59.3408z" Fill="#F38181" /><Path Data="M979.5072 856.8064h0.98816V404.9152H47.24224v60.71296c-0.04096 1.00352-0.29696 1.9456-0.29696 2.95424v378.40384c0 1.01376 0.256 1.95584 0.29696 2.95424v6.85568h0.6912c4.80256 33.50016 33.3312 59.3408 68.16256 59.3408h795.24352c34.83136 0.00512 63.36512-25.8304 68.16768-59.33056z" Fill="#E6E4E2" /><Path Data="M489.54368 646.2208c-4.83328 5.80608-9.02144 9.98912-19.98336 19.65568-6.12352 5.80608-12.5696 11.60704-18.688 17.40288-19.65568 18.37056-23.20896 22.89152-27.71456 38.03136h77.6704v43.19232H365.4656v-18.37056c0-25.13408 6.44096-44.14976 23.5264-62.848 11.92448-13.2096 25.7792-24.81152 38.99904-37.05856 19.01568-17.40288 22.88128-22.23616 22.88128-37.70368v-16.75776c0-4.51584 0-20.95104-17.40288-20.62848-11.60704 0-15.79008 6.76352-17.40288 11.60192-0.64512 1.93536-0.96768 4.51072-0.96768 9.344v31.90784h-47.69792v-29.32736c0-17.0752 0.96768-32.22528 14.50496-45.11744 9.02144-8.704 24.81664-16.75776 52.85376-16.75776 26.42944 0 41.25184 8.05888 50.2784 15.47264 2.2528 1.93024 9.02144 7.7312 12.5696 16.4352 2.89792 7.0912 3.8656 14.8224 3.8656 30.61248-0.00512 19.33312 0.64 34.79552-11.9296 50.91328zM654.87872 742.90688c-3.2256 5.16096-8.05888 9.02656-9.67168 10.31168-18.688 15.47264-42.86464 15.15008-50.2784 15.15008-25.45152 0-40.92928-8.05888-49.3056-15.15008-6.44608-5.4784-10.31168-11.60192-13.21984-19.33312-3.8656-11.27936-3.8656-22.56384-3.8656-34.16064v-103.45984c0-4.19328 0-8.704 0.32768-12.89216 0.31744-5.15072 1.28512-19.33312 11.60192-31.2576 8.704-10.63936 23.84896-19.01568 53.17632-19.01568 23.20896 0 53.17632 5.4784 63.16544 29.97248 2.90816 6.76352 3.87584 12.24192 3.87584 26.42944v15.79008h-47.05792v-11.92448c0-4.51584 0.64512-19.66592-16.75776-19.66592-19.33824 0-19.01568 16.11776-19.01568 21.59616v42.21952c6.44608-6.44608 14.50496-14.8224 34.80576-14.8224 27.71456 0 41.57952 13.85472 46.09024 24.81152 2.2528 5.80608 3.2256 9.67168 3.2256 20.95104v37.38624c-0.00512 12.89728 0.32256 25.78432-7.09632 37.06368z m-41.5744-65.41824c0-4.83328 1.6128-23.53152-17.72032-23.53152-4.83328 0-8.38656 0.65024-11.92448 3.54816-6.44608 5.4784-6.12864 13.85472-6.12864 21.26848v27.71456c0 5.80608-1.28512 21.91872 18.37056 21.91872 6.12352 0 9.02656-1.6128 11.60704-3.54816 5.79584-4.83328 6.12352-12.89216 6.12352-27.39712-0.00512-6.43584-0.00512-13.2096-0.32768-19.97312z" Fill="#5B5144" /><Path Data="M455.91552 325.95456V239.50848l-18.54464 86.44608h-25.52832l-18.55488-86.44608v86.44608h-25.35424V205.81376h38.79936l17.87392 88.14592 17.86368-88.14592h39.31136v120.1408h-25.86624zM550.05696 325.95456l-4.08064-27.40224h-22.29248l-4.25472 27.40224H491.008l24.33536-120.1408h38.79936l24.32512 120.1408h-28.41088z m-14.97088-101.08416l-8.16128 53.43744h16.16384l-8.00256-53.43744zM629.56032 283.75552v42.19904h-28.42112v-42.19904l-28.59008-77.93664h28.59008l14.62784 53.0944 14.63808-53.0944h29.10208l-29.94688 77.93664z" Fill="#FFFFFF" /></Grid></Viewbox>
</UserControl>
效果:
C#逻辑代码:
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;namespace XH.CustomLesson.Controls
{/// <summary>/// DateTimePicker.xaml 的交互逻辑/// </summary>public partial class DateTimePicker : UserControl, INotifyPropertyChanged{public event PropertyChangedEventHandler? PropertyChanged;public event EventHandler<DateTime> SeletedChanged;private int hourInt = DateTime.Now.Hour;public int HourInt{get { return hourInt; }set{hourInt = value;PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("HourInt"));}}private int minuteInt = DateTime.Now.Minute;public int MinuteInt{get { return minuteInt; }set{minuteInt = value;PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("MinuteInt"));}}private int secondInt = DateTime.Now.Second;public int SecondInt{get { return secondInt; }set{secondInt = value;PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("SecondInt"));}}public DateTime CurrentDateTime{get { return (DateTime)GetValue(CurrentDateTimeProperty); }set{SetValue(CurrentDateTimeProperty, value);}}// Using a DependencyProperty as the backing store for CurrentDateTime. This enables animation, styling, binding, etc...public static readonly DependencyProperty CurrentDateTimeProperty =DependencyProperty.Register("CurrentDateTime", typeof(DateTime), typeof(DateTimePicker), new PropertyMetadata(DateTime.Now,new PropertyChangedCallback(OnCurentDateTimeChanged)));private static void OnCurentDateTimeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e){(d as DateTimePicker).Refresh();}private void Refresh(){this.calendar.SelectedDate = this.CurrentDateTime; this.calendar.DisplayDate = this.CurrentDateTime; // 确保日历显示正确的月份HourInt = this.CurrentDateTime.Hour;MinuteInt = this.CurrentDateTime.Minute;SecondInt = this.CurrentDateTime.Second;}public DateTimePicker(){InitializeComponent();}private void Button_Click(object sender, RoutedEventArgs e){// 把日历和时间合并int year = calendar.SelectedDate.Value.Year;int month = calendar.SelectedDate.Value.Month;int day = calendar.SelectedDate.Value.Day;int.TryParse(this.tb_hour.Text.Trim(), out int hour);int.TryParse(this.tb_minute.Text.Trim(), out int minute);int.TryParse(this.tb_second.Text.Trim(), out int second);CurrentDateTime = new DateTime(year, month, day, hour, minute, second);this.popup.IsOpen = false;SeletedChanged?.Invoke(this, CurrentDateTime);}private void BtnHourUp_Click(object sender, RoutedEventArgs e){var hour_str = string.IsNullOrEmpty(this.tb_hour.Text) ? "0" : this.tb_hour.Text;HourInt = int.Parse(hour_str);HourInt++;HourInt %= 24;//this.tb_hour.Text = hourInt.ToString();}private void BtnHourDown_Click(object sender, RoutedEventArgs e){var hour_str = string.IsNullOrEmpty(this.tb_hour.Text) ? "0" : this.tb_hour.Text;HourInt = int.Parse(hour_str);HourInt--;HourInt = (HourInt + 24) % 24;}private void BtnMinuteDown_Click(object sender, RoutedEventArgs e){var minute_str = string.IsNullOrEmpty(this.tb_minute.Text) ? "0" : this.tb_minute.Text;MinuteInt = int.Parse(minute_str);MinuteInt--;MinuteInt = (MinuteInt + 60) % 60;}private void BtnMinuteUp_Click(object sender, RoutedEventArgs e){var minute_str = string.IsNullOrEmpty(this.tb_minute.Text) ? "0" : this.tb_minute.Text;MinuteInt = int.Parse(minute_str);MinuteInt++;MinuteInt %= 60;}private void BtnSecondUp_Click(object sender, RoutedEventArgs e){var second_str = string.IsNullOrEmpty(this.tb_second.Text) ? "0" : this.tb_second.Text;SecondInt = int.Parse(second_str);SecondInt++;SecondInt %= 60;}private void BtnSecondDown_Click(object sender, RoutedEventArgs e){var second_str = string.IsNullOrEmpty(this.tb_second.Text) ? "0" : this.tb_second.Text;SecondInt = int.Parse(second_str);SecondInt--;SecondInt = (SecondInt + 60) % 60;}private void tb_hour_TextChanged(object sender, TextChangedEventArgs e){HourInt = int.Parse(tb_hour.Text);if (HourInt >= 24 || HourInt < 0)HourInt = 0;}private void tb_minute_TextChanged(object sender, TextChangedEventArgs e){MinuteInt = int.Parse(tb_minute.Text);if (MinuteInt >= 60 || MinuteInt < 0)MinuteInt = 0;}private void tb_second_TextChanged(object sender, TextChangedEventArgs e){SecondInt = int.Parse(tb_second.Text);if (SecondInt >= 60 || SecondInt < 0)SecondInt = 0;}private void Button_Click_1(object sender, RoutedEventArgs e){this.popup.IsOpen = false;}}
}
使用自定义控件代码:
<c:DateTimePicker HorizontalAlignment="Center"SeletedChanged="DateTimePicker_SeletedChanged" VerticalAlignment="Top"Width="200" CurrentDateTime="{Binding Current,RelativeSource={RelativeSource AncestorType=Window}}" />
CustomControl 自定义控件
案例:自定义数值控件
XAML代码:
<ResourceDictionaryxmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:c="clr-namespace:XH.CustomLesson.Controls"xmlns:local="clr-namespace:XH.CustomLesson"><Style TargetType="{x:Type c:NumericBox}"><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type c:NumericBox}"><Border Background="{TemplateBinding Background}"BorderBrush="{TemplateBinding BorderBrush}"BorderThickness="{TemplateBinding BorderThickness}"CornerRadius="5"><Grid><Grid.ColumnDefinitions><ColumnDefinition/><ColumnDefinition Width="30"/></Grid.ColumnDefinitions><TextBox Name="PART_Value" VerticalAlignment="Center" Margin="3,5" BorderThickness="0"Foreground="{TemplateBinding Foreground}"/><UniformGrid Rows="2" Grid.Column="1"><RepeatButton Content="+" Background="Transparent" BorderThickness="1,0,0,0" Name="PART_IncreaseButton"BorderBrush="#DDD"/><RepeatButton Content="-" Background="Transparent" BorderThickness="1,1,0,0" Name="PART_DecreaseButton"BorderBrush="#DDD"/></UniformGrid></Grid></Border></ControlTemplate></Setter.Value></Setter></Style></ResourceDictionary>
C#逻辑代码:
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Media;namespace XH.CustomLesson.Controls
{/// <summary>/// 按照步骤 1a 或 1b 操作,然后执行步骤 2 以在 XAML 文件中使用此自定义控件。////// 步骤 1a) 在当前项目中存在的 XAML 文件中使用该自定义控件。/// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根/// 元素中:////// xmlns:MyNamespace="clr-namespace:XH.CustomLesson.Controls"///////// 步骤 1b) 在其他项目中存在的 XAML 文件中使用该自定义控件。/// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根/// 元素中:////// xmlns:MyNamespace="clr-namespace:XH.CustomLesson.Controls;assembly=XH.CustomLesson.Controls"////// 您还需要添加一个从 XAML 文件所在的项目到此项目的项目引用,/// 并重新生成以避免编译错误:////// 在解决方案资源管理器中右击目标项目,然后依次单击/// “添加引用”->“项目”->[浏览查找并选择此项目]///////// 步骤 2)/// 继续操作并在 XAML 文件中使用控件。////// <MyNamespace:NumericBox/>////// </summary>/// [TemplatePart(Name = "PART_Vlaue", Type = typeof(TextBox))]public class NumericBox : Control{TextBox txtValue = new TextBox();public int Value{get { return (int)GetValue(ValueProperty); }set { SetValue(ValueProperty, value); }}// Using a DependencyProperty as the backing store for Value. This enables animation, styling, binding, etc...public static readonly DependencyProperty ValueProperty =DependencyProperty.Register("Value",typeof(int),typeof(NumericBox),new PropertyMetadata(0, new PropertyChangedCallback(OnValueChanged)));private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e){var nb = (d as NumericBox);if (nb.txtValue == null) return;if (nb.Value > 30)nb.txtValue.Foreground = Brushes.Red;else if(nb.Value >0 && nb.Value < 30)nb.txtValue.Foreground = Brushes.Black;else if (nb.Value < 0)nb.txtValue.Foreground = Brushes.Orange;}static NumericBox(){DefaultStyleKeyProperty.OverrideMetadata(typeof(NumericBox), new FrameworkPropertyMetadata(typeof(NumericBox)));}// 应用模板public override void OnApplyTemplate(){base.OnApplyTemplate();// 获取模板中的事件txtValue = base.GetTemplateChild("PART_Value") as TextBox;var btnIncrease = base.GetTemplateChild("PART_IncreaseButton") as RepeatButton;var btnDecrease = base.GetTemplateChild("PART_DecreaseButton") as RepeatButton;if (txtValue != null){// 建立对象中的Value属性和模板中的TextBox控件的Text属性的绑定Binding binding = new Binding("Value");binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;binding.RelativeSource = new RelativeSource() { AncestorType = typeof(NumericBox), Mode = RelativeSourceMode.FindAncestor };txtValue.SetBinding(TextBox.TextProperty, binding);}if (btnIncrease != null)btnIncrease.Click += BtnIncrease_Click;if (btnDecrease != null)btnDecrease.Click += BtnDecrease_Click;}private void BtnDecrease_Click(object sender, RoutedEventArgs e){this.Value--;}private void BtnIncrease_Click(object sender, RoutedEventArgs e){this.Value++;}}
}
使用部分代码:
<c:NumericBox VerticalAlignment="Bottom" Width="200" BorderBrush="#ddd"BorderThickness="1" Margin="20"/>
UserControl与CustomControl区别
- 自定义控件:注重控件对象的功能,必须遵守WPF的控件规则
-
- 完全自己实现一个控件 继承现有控件进行功能扩展,并且添加新功能 WPF的控件要求
- 后台代码(控制逻辑)和Generic.Xaml(样式 模板)进行组合
- 支持模板重写
- 继承Control
- 用户控件:注重复合控件组合使用,非常灵活,可以根据控件开发人员自己的意愿进行功能处理
-
- 多个现有控件的集合,组成一个可复用的控件组
- XAML和后台代码组成 绑定非常紧密
- 不支持模板重写、样式
- 继承UserControl
案例
工业仪表
XAML代码:
<UserControl x:Class="XH.CustomLesson.Controls.Instrument"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:XH.CustomLesson.Controls"mc:Ignorable="d" d:DesignHeight="400" d:DesignWidth="400"><Grid><Border Name="border" Background="#FF030A28"><Border.Effect><DropShadowEffect BlurRadius="20" Opacity="0.5" ShadowDepth="0" Direction="0" Color="#FF3CAFFF"/></Border.Effect><Grid><Path Stroke="#333CAFFF" StrokeThickness="10" Name="circle" RenderTransformOrigin="0.5,0.5"><Path.RenderTransform><RotateTransform Angle="-45"/></Path.RenderTransform></Path><Canvas x:Name="canvasPlate" RenderTransformOrigin="0.5,0.5" Margin="0"><Canvas.RenderTransform><RotateTransform Angle="-45"/></Canvas.RenderTransform></Canvas><Path Data="" Name="plateBorder" Stroke="#FF3CAFFF" StrokeThickness="3" RenderTransformOrigin="0.5,0.5"Width="{Binding ElementName=border,Path=Width}"Height="{Binding ElementName=border,Path=Height}"><Path.RenderTransform><RotateTransform Angle="-45"/></Path.RenderTransform></Path><Path Data="M200 205,360 200,200 195,195 200 200 205" Fill="Red" RenderTransformOrigin="0.5,0.5" Name="pointer"><Path.RenderTransform><RotateTransform Angle="135" x:Name="rtPointer"/></Path.RenderTransform></Path><Border Width="60" Height="60" CornerRadius="30" Background="#FF030A28"><Border.Effect><DropShadowEffect BlurRadius="20" Opacity="0.3" ShadowDepth="0" Direction="0" Color="#FF3CAFFF"/></Border.Effect><StackPanel VerticalAlignment="Center" HorizontalAlignment="Center"><TextBlock Foreground="White" VerticalAlignment="Center" HorizontalAlignment="Center"><Run Text="{Binding Value,RelativeSource={RelativeSource AncestorType=UserControl}}"FontSize="20"/><Run Text="m³/H" FontSize="8"/></TextBlock><TextBlock Text="NATURAL GAS" Foreground="#FF8CBEF0" VerticalAlignment="Center" HorizontalAlignment="Center"FontSize="6"/></StackPanel></Border></Grid></Border></Grid>
</UserControl>
C#代码:
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;namespace XH.CustomLesson.Controls
{/// <summary>/// Instrument.xaml 的交互逻辑/// </summary>public partial class Instrument : UserControl{// 当前值 public double Value{get { return (double)GetValue(ValueProperty); }set { SetValue(ValueProperty, value); }}public static readonly DependencyProperty ValueProperty =DependencyProperty.Register("Value", typeof(double), typeof(Instrument),new PropertyMetadata(default(double), new PropertyChangedCallback(OnPropertyChanged)));// 最小刻度public double Minimum{get { return (double)GetValue(MinimumProperty); }set { SetValue(MinimumProperty, value); }}public static readonly DependencyProperty MinimumProperty =DependencyProperty.Register("Minimum", typeof(double), typeof(Instrument),new PropertyMetadata(default(double), new PropertyChangedCallback(OnPropertyChanged)));// 最大刻度public double Maximum{get { return (double)GetValue(MaximumProperty); }set { SetValue(MaximumProperty, value); }}public static readonly DependencyProperty MaximumProperty =DependencyProperty.Register("Maximum", typeof(double), typeof(Instrument),new PropertyMetadata(default(double), new PropertyChangedCallback(OnPropertyChanged)));间隔//public double Interval//{// get { return (double)GetValue(IntervalProperty); }// set { SetValue(IntervalProperty, value); }//}//public static readonly DependencyProperty IntervalProperty =// DependencyProperty.Register("Interval", typeof(double), typeof(Instrument), new PropertyMetadata(default(double), new PropertyChangedCallback(OnPropertyChanged)));// 大刻度的个数public int ScaleCount{get { return (int)GetValue(ScaleCountProperty); }set { SetValue(ScaleCountProperty, value); }}public static readonly DependencyProperty ScaleCountProperty =DependencyProperty.Register("ScaleCount", typeof(int), typeof(Instrument),new PropertyMetadata(default(int), new PropertyChangedCallback(OnPropertyChanged)));// 刻度的厚度public double ScaleThickness{get { return (double)GetValue(ScaleThicknessProperty); }set { SetValue(ScaleThicknessProperty, value); }}public static readonly DependencyProperty ScaleThicknessProperty =DependencyProperty.Register("ScaleThickness", typeof(double), typeof(Instrument),new PropertyMetadata(default(double), new PropertyChangedCallback(OnPropertyChanged)));// 刻度的颜色public Brush ScaleBrush{get { return (Brush)GetValue(ScaleBrushProperty); }set { SetValue(ScaleBrushProperty, value); }}public static readonly DependencyProperty ScaleBrushProperty =DependencyProperty.Register("ScaleBrush", typeof(Brush), typeof(Instrument),new PropertyMetadata(default(Brush), new PropertyChangedCallback(OnPropertyChanged)));// 指针的颜色public Brush PointerBrush{get { return (Brush)GetValue(PointerBrushProperty); }set { SetValue(PointerBrushProperty, value); }}public static readonly DependencyProperty PointerBrushProperty =DependencyProperty.Register("PointerBrush", typeof(Brush), typeof(Instrument),new PropertyMetadata(default(Brush), new PropertyChangedCallback(OnPropertyChanged)));// 刻度字体大小 public new double FontSize{get { return (double)GetValue(FontSizeProperty); }set { SetValue(FontSizeProperty, value); }}public static new readonly DependencyProperty FontSizeProperty =DependencyProperty.Register("FontSize", typeof(double), typeof(Instrument),new PropertyMetadata(9.0, new PropertyChangedCallback(OnPropertyChanged)));public Instrument(){InitializeComponent();SetCurrentValue(MinimumProperty, 0d);SetCurrentValue(MaximumProperty, 100d);//SetCurrentValue(IntervalProperty, 10d);SizeChanged += (se, ev) => { Refresh(); };}static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)=> (d as Instrument).Refresh();private void Refresh(){// 圆this.border.Width = Math.Min(RenderSize.Width, RenderSize.Height);this.border.Height = Math.Min(RenderSize.Width, RenderSize.Height);this.border.CornerRadius = new CornerRadius(this.border.Width / 2);// 半径double radius = this.border.Width / 2;this.canvasPlate.Children.Clear();if (ScaleCount <= 0 || radius <= 0) return;// 画边string borderPathData = $"M4,{radius}A{radius - 4} {radius - 4} 0 1 1 {radius} {this.border.Height - 4}";// 将字符串转换成Geometryvar converter = TypeDescriptor.GetConverter(typeof(Geometry));//this.plateBorder.Data = (Geometry)converter.ConvertFrom(borderPathData);this.plateBorder.Data = PathGeometry.Parse(borderPathData);// 计算刻度double label = this.Minimum;double interval = 0;double step = 270.0 / (this.Maximum - this.Minimum);// 计算小刻度for (int i = 0; i < this.Maximum - this.Minimum; i++){//添加刻度线Line lineScale = new Line();// 角度需要转换弧度lineScale.X1 = radius - (radius - 13) * Math.Cos(step * i * Math.PI / 180);lineScale.Y1 = radius - (radius - 13) * Math.Sin(step * i * Math.PI / 180);lineScale.X2 = radius - (radius - 8) * Math.Cos(step * i * Math.PI / 180);lineScale.Y2 = radius - (radius - 8) * Math.Sin(step * i * Math.PI / 180);lineScale.Stroke = this.ScaleBrush;lineScale.StrokeThickness = this.ScaleThickness;this.canvasPlate.Children.Add(lineScale);}// 计算大刻度do{//添加刻度线Line lineScale = new Line();lineScale.X1 = radius - (radius - 20) * Math.Cos(interval * step * Math.PI / 180);lineScale.Y1 = radius - (radius - 20) * Math.Sin(interval * step * Math.PI / 180);lineScale.X2 = radius - (radius - 8) * Math.Cos(interval * step * Math.PI / 180);lineScale.Y2 = radius - (radius - 8) * Math.Sin(interval * step * Math.PI / 180);lineScale.Stroke = this.ScaleBrush;lineScale.StrokeThickness = this.ScaleThickness;this.canvasPlate.Children.Add(lineScale);TextBlock txtScale = new TextBlock();txtScale.Text = label.ToString("0");txtScale.Width = 34;txtScale.TextAlignment = TextAlignment.Center;txtScale.Foreground = new SolidColorBrush(Colors.White);txtScale.RenderTransform = new RotateTransform() { Angle = 45, CenterX = 17, CenterY = 8 };txtScale.FontSize = this.FontSize;Canvas.SetLeft(txtScale, radius - (radius - 34) * Math.Cos(interval * step * Math.PI / 180) - 17);Canvas.SetTop(txtScale, radius - (radius - 34) * Math.Sin(interval * step * Math.PI / 180) - 8);this.canvasPlate.Children.Add(txtScale);interval += (this.Maximum - this.Minimum) / this.ScaleCount;label += (this.Maximum - this.Minimum) / this.ScaleCount;} while (interval <= this.Maximum - this.Minimum);// 修改指针string sData = "M{0} {1},{2} {0},{0} {3},{3} {0},{0} {1}";sData = string.Format(sData, radius, radius + 2, this.border.Width - radius / 10, radius - 4);converter = TypeDescriptor.GetConverter(typeof(Geometry));this.pointer.Data = (Geometry)converter.ConvertFrom(sData);this.pointer.Fill = this.PointerBrush;//DoubleAnimation da = new DoubleAnimation((Value - Minimum) * step + 135, new Duration(TimeSpan.FromMilliseconds(200)));//this.rtPointer.BeginAnimation(RotateTransform.AngleProperty, da);this.rtPointer.Angle = (Value - Minimum) * step + 135;// 修改圆 M100 200 A100 100 0 1 1 200 300// 厚度double thickness = radius / 2;this.circle.StrokeThickness = thickness;double startX = radius - thickness / 2;double startY = radius;double endX = radius - (radius - thickness / 2) * Math.Cos((Value - Minimum) * step * Math.PI / 180);double endY = radius - (radius - thickness / 2) * Math.Sin((Value - Minimum) * step * Math.PI / 180);int isLarge = 1;if ((Value - Minimum) * step < 180)isLarge = 0;sData = $"M{startX},{startY}A{radius / 2} {radius / 2} 0 1 1 {endX} {endY}";sData = $"M{thickness / 2},{radius}A{radius - thickness / 2} {radius - thickness / 2} 0 {isLarge} 1 {endX} {endY}";//sData = string.Format(sData, radius * 0.5, radius, radius * 1.5);this.circle.Data = (Geometry)converter.ConvertFrom(sData);this.circle.Visibility = Visibility.Visible;if (this.border.Width < 200)this.circle.Visibility = Visibility.Collapsed;}}
}
使用代码:
<c:Instrument Height="200" Width="200" Maximum="100" Value="25" Minimum="0"ScaleCount="10" ScaleThickness="0.5" ScaleBrush="White"PointerBrush="Red" FontSize="9"/>
效果展示:
各种常见开关
自定义控件:代码:
<Style TargetType="{x:Type c:Switch}"><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type c:Switch}"><Grid><Border Width="{Binding RelativeSource={RelativeSource Self},Path=ActualHeight}" CornerRadius="{Binding RelativeSource={RelativeSource Self},Path=ActualHeight}"Visibility="Collapsed" Name="dropdown" Margin="-23"><Border.Background><RadialGradientBrush><GradientStop Color="Transparent" Offset="1"/><GradientStop Color="#5500D787" Offset="0.7"/><GradientStop Color="Transparent" Offset="0.59"/></RadialGradientBrush></Border.Background></Border><Border Width="{Binding RelativeSource={RelativeSource Self},Path=ActualHeight}"BorderBrush="DarkGreen" BorderThickness="5"CornerRadius="{Binding RelativeSource={RelativeSource Self},Path=ActualHeight}"Background="Gray" Name="bor"><Border Background="#FF00C88C" Margin="2" Name="bor1"Width="{Binding RelativeSource={RelativeSource Self},Path=ActualHeight}" CornerRadius="{Binding RelativeSource={RelativeSource Self},Path=ActualHeight}"/></Border></Grid><ControlTemplate.Triggers><Trigger Property="IsChecked" Value="True"><Trigger.EnterActions><BeginStoryboard><Storyboard ><ColorAnimation To="White" Duration="0:0:0.5"Storyboard.TargetName="bor1"Storyboard.TargetProperty="Background.Color"/><ColorAnimation To="#FF32FAC8" Duration="0:0:0.5"Storyboard.TargetName="bor"Storyboard.TargetProperty="BorderBrush.Color"/><ObjectAnimationUsingKeyFrames Storyboard.TargetName="dropdown"Storyboard.TargetProperty="Visibility"><DiscreteObjectKeyFrame KeyTime="0:0:0.3"><DiscreteObjectKeyFrame.Value><Visibility>Visible</Visibility></DiscreteObjectKeyFrame.Value></DiscreteObjectKeyFrame></ObjectAnimationUsingKeyFrames></Storyboard></BeginStoryboard></Trigger.EnterActions><Trigger.ExitActions><BeginStoryboard><Storyboard ><ColorAnimation Storyboard.TargetName="bor1"Storyboard.TargetProperty="Background.Color"/><ColorAnimation Storyboard.TargetName="bor"Storyboard.TargetProperty="BorderBrush.Color"/><ObjectAnimationUsingKeyFrames Storyboard.TargetName="dropdown"Storyboard.TargetProperty="Visibility"><DiscreteObjectKeyFrame KeyTime="0:0:0.3"><DiscreteObjectKeyFrame.Value><Visibility>Collapsed</Visibility></DiscreteObjectKeyFrame.Value></DiscreteObjectKeyFrame></ObjectAnimationUsingKeyFrames></Storyboard></BeginStoryboard></Trigger.ExitActions></Trigger></ControlTemplate.Triggers></ControlTemplate></Setter.Value></Setter>
</Style>
C#代码:
public class Switch :ToggleButton
{static Switch(){DefaultStyleKeyProperty.OverrideMetadata(typeof(Switch), new FrameworkPropertyMetadata(typeof(Switch)));}
}
使用场景:
<UniformGrid Rows="1" HorizontalAlignment="Center"><c:Switch Height="60" IsChecked="False" Margin="0 0 20 0" /><c:Switch Height="60" IsChecked="True" Margin="0 0 20 0"/><c:Switch Height="60" IsChecked="False" Style="{StaticResource RotarySwitchStyle}" Margin="0 0 20 0"/><c:Switch Height="60" IsChecked="True" Style="{StaticResource RotarySwitchStyle}" Margin="0 0 20 0"/><c:Switch Height="60" IsChecked="False" Style="{StaticResource ButtonSwitchStyle}" Margin="0 0 20 0"/><c:Switch Height="60" IsChecked="True" Style="{StaticResource ButtonSwitchStyle}" Margin="0 0 20 0"/><ToggleButton Height="60" Style="{StaticResource Button2SwitchStyle}" Margin="0 0 20 0"/>
</UniformGrid>
其他按钮自定义样式:其实都是ToggleButton的自定义模板
<Style TargetType="c:Switch" x:Key="RotarySwitchStyle"><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="c:Switch"><Grid><Border Background="#FF3C3C3C" Width="{Binding RelativeSource={RelativeSource Self},Path=ActualHeight}"CornerRadius="{Binding RelativeSource={RelativeSource Self},Path=ActualHeight}"/><Border BorderBrush="Black" BorderThickness="1" Margin="8"Width="{Binding RelativeSource={RelativeSource Self},Path=ActualHeight}"CornerRadius="{Binding RelativeSource={RelativeSource Self},Path=ActualHeight}"/><Border Width="12" CornerRadius="6" Background="#FF3C3C3C"RenderTransformOrigin="0.5,0.5"><Border.Effect><DropShadowEffect BlurRadius="14" Color="Black" Opacity="0.9" Direction="0"ShadowDepth="0"/></Border.Effect><Border.RenderTransform><RotateTransform Angle="-30" x:Name="rt"/></Border.RenderTransform><Grid><Grid.RowDefinitions><RowDefinition Height="1*"/><RowDefinition/></Grid.RowDefinitions><Border Background="White" Margin="3,3" CornerRadius="4"/></Grid></Border></Grid><ControlTemplate.Triggers><Trigger Property="IsChecked" Value="True"><Trigger.EnterActions><BeginStoryboard><Storyboard><DoubleAnimation To="30" Duration="0:0:0.2"Storyboard.TargetName="rt"Storyboard.TargetProperty="Angle"/></Storyboard></BeginStoryboard></Trigger.EnterActions><Trigger.ExitActions><BeginStoryboard><Storyboard><DoubleAnimation Duration="0:0:0.2"Storyboard.TargetName="rt"Storyboard.TargetProperty="Angle"/></Storyboard></BeginStoryboard></Trigger.ExitActions></Trigger></ControlTemplate.Triggers></ControlTemplate></Setter.Value></Setter>
</Style><Style TargetType="c:Switch" x:Key="ButtonSwitchStyle"><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="c:Switch"><Grid><Grid.ColumnDefinitions><ColumnDefinition/><ColumnDefinition/></Grid.ColumnDefinitions><Border x:Name="borWidth"/><Border Width="{Binding ElementName=borWidth,Path=ActualWidth}"Height="{Binding ElementName=borWidth,Path=ActualHeight}"Grid.ColumnSpan="2"Background="#FF3C3C3C" CornerRadius="3"><Grid><Border Background="#FFA24F3F" Margin="6"/><Grid Margin="6,18,6,6" Name="grid"><Border><Border.Background><LinearGradientBrush StartPoint="0,0" EndPoint="0,1" x:Name="lgb"><GradientStop Color="#FF4B4B4B" Offset="0"/><GradientStop Color="#FF863424" Offset="0.7"/></LinearGradientBrush></Border.Background></Border><Border><Border.OpacityMask><LinearGradientBrush StartPoint="0,0" EndPoint="0,1"><GradientStop Color="Black" Offset="1" x:Name="gs1"/><GradientStop Color="Transparent" Offset="0" x:Name="gs2"/></LinearGradientBrush></Border.OpacityMask><Grid TextBlock.FontSize="16" Margin="0,3"><TextBlock Text="I" VerticalAlignment="Top" HorizontalAlignment="Center" Foreground="White"/><TextBlock Text="O" VerticalAlignment="Bottom" HorizontalAlignment="Center" Foreground="White"/></Grid></Border></Grid></Grid></Border></Grid><ControlTemplate.Triggers><Trigger Property="IsChecked" Value="True"><Trigger.EnterActions><BeginStoryboard><Storyboard><ThicknessAnimation To="6,6,6,18"Duration="0:0:0.2"Storyboard.TargetName="grid"Storyboard.TargetProperty="Margin"/><DoubleAnimation To="0" Duration="0:0:0.2"Storyboard.TargetName="gs1"Storyboard.TargetProperty="Offset"/><DoubleAnimation To="1" Duration="0:0:0.2"Storyboard.TargetName="gs2"Storyboard.TargetProperty="Offset"/><PointAnimation To="0,1" Duration="0:0:0.2"Storyboard.TargetName="lgb"Storyboard.TargetProperty="StartPoint"/><PointAnimation To="0,0" Duration="0:0:0.2"Storyboard.TargetName="lgb"Storyboard.TargetProperty="EndPoint"/></Storyboard></BeginStoryboard></Trigger.EnterActions><Trigger.ExitActions><BeginStoryboard><Storyboard><ThicknessAnimation Duration="0:0:0.2"Storyboard.TargetName="grid"Storyboard.TargetProperty="Margin"/><DoubleAnimation Duration="0:0:0.2"Storyboard.TargetName="gs1"Storyboard.TargetProperty="Offset"/><DoubleAnimation Duration="0:0:0.2"Storyboard.TargetName="gs2"Storyboard.TargetProperty="Offset"/><PointAnimation Duration="0:0:0.2"Storyboard.TargetName="lgb"Storyboard.TargetProperty="StartPoint"/><PointAnimation Duration="0:0:0.2"Storyboard.TargetName="lgb"Storyboard.TargetProperty="EndPoint"/></Storyboard></BeginStoryboard></Trigger.ExitActions></Trigger></ControlTemplate.Triggers></ControlTemplate></Setter.Value></Setter>
</Style><Style TargetType="ToggleButton" x:Key="Button2SwitchStyle"><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="ToggleButton"><Grid><Grid.ColumnDefinitions><ColumnDefinition/><ColumnDefinition/></Grid.ColumnDefinitions><Border x:Name="borWidth"/><Border Width="{Binding ElementName=borWidth,Path=ActualWidth}"Height="{Binding ElementName=borWidth,Path=ActualHeight}"Grid.ColumnSpan="2"Background="#FF3C3C3C" CornerRadius="3"><Grid><Border Background="#FFA24F3F" Margin="6"/><Grid Margin="6,18,6,6" Name="grid"><Border><Border.Background><LinearGradientBrush StartPoint="0,0" EndPoint="0,1" x:Name="lgb"><GradientStop Color="#FF4B4B4B" Offset="0"/><GradientStop Color="#FF863424" Offset="0.7"/></LinearGradientBrush></Border.Background></Border><Border><Border.OpacityMask><LinearGradientBrush StartPoint="0,0" EndPoint="0,1"><GradientStop Color="Black" Offset="1" x:Name="gs1"/><GradientStop Color="Transparent" Offset="0" x:Name="gs2"/></LinearGradientBrush></Border.OpacityMask><Grid TextBlock.FontSize="16" Margin="0,3"><TextBlock Text="I" VerticalAlignment="Top" HorizontalAlignment="Center" Foreground="White"/><TextBlock Text="O" VerticalAlignment="Bottom" HorizontalAlignment="Center" Foreground="White"/></Grid></Border></Grid></Grid></Border></Grid><ControlTemplate.Triggers><Trigger Property="IsChecked" Value="True"><Trigger.EnterActions><BeginStoryboard><Storyboard><ThicknessAnimation To="6,6,6,18"Duration="0:0:0.2"Storyboard.TargetName="grid"Storyboard.TargetProperty="Margin"/><DoubleAnimation To="0" Duration="0:0:0.2"Storyboard.TargetName="gs1"Storyboard.TargetProperty="Offset"/><DoubleAnimation To="1" Duration="0:0:0.2"Storyboard.TargetName="gs2"Storyboard.TargetProperty="Offset"/><PointAnimation To="0,1" Duration="0:0:0.2"Storyboard.TargetName="lgb"Storyboard.TargetProperty="StartPoint"/><PointAnimation To="0,0" Duration="0:0:0.2"Storyboard.TargetName="lgb"Storyboard.TargetProperty="EndPoint"/></Storyboard></BeginStoryboard></Trigger.EnterActions><Trigger.ExitActions><BeginStoryboard><Storyboard><ThicknessAnimation Duration="0:0:0.2"Storyboard.TargetName="grid"Storyboard.TargetProperty="Margin"/><DoubleAnimation Duration="0:0:0.2"Storyboard.TargetName="gs1"Storyboard.TargetProperty="Offset"/><DoubleAnimation Duration="0:0:0.2"Storyboard.TargetName="gs2"Storyboard.TargetProperty="Offset"/><PointAnimation Duration="0:0:0.2"Storyboard.TargetName="lgb"Storyboard.TargetProperty="StartPoint"/><PointAnimation Duration="0:0:0.2"Storyboard.TargetName="lgb"Storyboard.TargetProperty="EndPoint"/></Storyboard></BeginStoryboard></Trigger.ExitActions></Trigger></ControlTemplate.Triggers></ControlTemplate></Setter.Value></Setter>
</Style>
显示效果:
相关文章:
WPF自定义控件
控件模板 顾名思义就是在原有的控件上进行模版修改成自己需要的样式 把ProgressBar修改为一个水液面的进度条 <Window x:Class"XH.CustomLesson.MainWindow"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://s…...
Java中的全局异常处理器 -- GlobalExceptionHandler
开发记录:全局异常处理器笔记 import lombok.extern.slf4j.Slf4j; import org.mybatis.spring.MyBatisSystemException; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.redis.RedisConnectionFailureException; im…...
R语言文本挖掘-万字详细解析tm包
tm包(Text Mining Package)是R语言中用于文本挖掘的强大工具包,它提供了一系列的功能来处理和分析文本数据。偶然看到这个包,我们一起看看其中的基本功能: 数据载入:tm包支持从多种数据源载入文本数据&…...
JWT中的Token
1.JWT是什么? jwt(json web token的缩写)是一个开放标准(rfc7519),它定义了一种紧凑的、自包含的方式,用于在各方之间以json对象安全地传输信息,此信息可以验证和信任,因…...
苹果在iOS 18.1中向第三方开发者开放iPhone的NFC芯片
苹果公司今天宣布,开发者很快就能首次在自己的应用程序中提供 NFC 交易功能,而目前这主要是Apple Pay独有的功能。从今年晚些时候的 iOS 18.1 开始,开发者将可以使用新的 API 提供独立于 Apple Pay 和 Apple Wallet 的应用内非接触式交易。 这…...
系统开发之禁止卸载应用名单
本文目的主要是记录自己系统(Android7.1系统)开发实现代码,以便后期通用的功能可以直接使用,不需要再去通过搜索然后筛选再验证的繁琐流程,大大减小自己的开发时间。 我实现思路是在系统内新增自己的数据库用来记录禁止…...
wait 和 notify
目录 wait() 方法 notify() 方法 notifyAll() 方法 nofity 和 notifyAll wait 和 notify wait 和 sleep 的区别 wait 和 join 的区别 由于线程之间是抢占式执行的,因此,线程之间执行的先后顺序难以预知,但是,在实际开发中&…...
docker 启动 mongo,redis,nacos.
docker run --name mymongodb -e MONGO_INITDB_ROOT_USERNAMEadmin -e MONGO_INITDB_ROOT_PASSWORDXiaoyusadsad -p 27017:27017 -v /path/to/mongo-data:/data/db -d mongodb/mongodb-community-server:4.4.18-ubuntu2004-v 的目录必须是绝对目录 目录必须 chmod 777 /path/…...
Docker Swarm 搭建
Docker Swarm 搭建 1. 环境介绍 操作系统Centos 7Centos 7Centos 7内核版本Linux 3.10.0-957.el7.x86_64Linux 3.10.0-957.el7.x86_64Linux 3.10.0-957.el7.x86_64主机名称swarm-managerswarm-worker1swarm-worker2IP192.168.1.100192.168.1.200192.168.1.250Docker Domain20…...
浅述TSINGSEE青犀EasyCVR视频汇聚平台与海康安防平台的区别对比
在我们的很多项目中都遇到过用户的咨询:TSINGSEE青犀EasyCVR视频汇聚平台与海康平台的区别在哪里?确实,在安防视频监控领域,EasyCVR视频汇聚平台与海康威视平台是两个备受关注的选择。它们各自具有独特的功能和优势,适…...
设计模式系列:策略模式的设计与实践
一、背景 策略模式(Strategy Pattern)是一种行为设计模式,它定义了一系列的算法,并将每一个算法封装起来,使它们可以相互替换。策略模式让算法的变化独立于使用算法的客户。 二、结构 策略模式主要包含三个角色&…...
数据挖掘之数据预处理
数据预处理是数据挖掘中的一个关键步骤,它的主要目的是对原始数据进行清洗、转换和格式化,以确保其质量和一致性,从而为后续的数据挖掘任务(如分类、回归、聚类等)提供可靠的数据基础。数据预处理一般包括以下几个主要…...
RocketMQ核心知识点整理,值得收藏!
1. 基本概念 Topic: 消息类别的集合,如订单消息发送到order_topic。标签(Tag): 同一Topic下区分不同消息的标志,实现精细化消息管理。ConsumeGroup: 消息消费组,可订阅多个Topic,一个Topic可被多个消费组订…...
微信小程序骨架屏
骨架屏是常用的一种优化方案,针对于页面还未加载完时给用户的一种反馈方式。如果自己要写骨架屏有点复杂因为页面的元素过多且不稳定,这边直接使用微信开发工具生成骨架屏。也不只有微信开发工具有像常用的抖音开发工具,字节开发工具都有对应…...
Window下node安装以及配置
在 Windows 下安装 Node.js 非常简单,你可以通过官方提供的安装程序或者使用多版本管理工具(如 NVM-Win)来进行安装。下面是两种方法的具体步骤: 1. 安装 Node.js程序 步骤如下: 访问官方网站: 访问 Node…...
校园疫情防控系统--论文pf
TOC springboot432校园疫情防控系统--论文pf 课题的来源 2019年在我国武汉爆发了一场规模非常庞大、传播速度十分迅速、对人体危害及其严重的新冠肺炎疫情。引发此次急性感染性新冠肺炎疫情的冠状病毒传播性较强,其传播主要是通过呼吸道飞沫和密切接触这两个途径…...
在Debian 9上使用Apt安装Java的方法
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。 介绍 Java 和 JVM(Java 虚拟机)是许多软件的必备组件,包括 Tomcat、Jetty、Glassfish、Cassandra 和…...
人工智能在网络安全中的三大支柱
人工智能 (AI) 席卷了网络安全行业,各种供应商都在努力将 AI 融入其解决方案中。但 AI 与安全之间的关系不仅仅在于实现 AI 功能,还在于攻击者和防御者如何利用该技术改变现代威胁形势。它还涉及如何开发、更新和保护这些 AI 模型。如今,网络…...
rk3568mpp终端学习笔记
RK3568Terminal封装MppGraph 通过脚本取和设置音量/zigsun/bin/linux/bin.debug.Linux.rk3568/get_record_voice_value.sh /zigsun/bin/linux/bin.debug.Linux.rk3568/set_record_voice_value.sh class RK3568Terminal : public IAVLinkManager, p…...
【C++继承】赋值兼容转换作用域派生类的默认成员函数
1.继承的概念 继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能,这样产生新的类,称派生类(或子类)。继承呈现了面向对象程序设计的层次结构…...
HTML5+JavaScript绘制彩虹和云朵
HTML5JavaScript绘制彩虹和云朵 彩虹,简称虹,是气象中的一种光学现象,当太阳光照射到半空中的水滴,光线被折射及反射,在天空上形成拱形的七彩光谱,由外圈至内圈呈红、橙、黄、绿、蓝、靛、紫七种颜色。事实…...
MySQL——单表查询(二)按条件查询(2)带 IN 关键字的查询
IN 关键字用于判断某个字段的值是否在指定集合中,如果字段的值在集合中,则满足条件,该字段所在的记录将被查询出来。其语法格式如下所示: SELECT *|字段名 1,字段名 2,… FROM 表名 WHERE 字段名 [NOT〕IN(元素 1,元素 2,…) 在上…...
【mysql】mysql 用户管理---创建、权限管理等等
本站以分享各种运维经验和运维所需要的技能为主 《python零基础入门》:python零基础入门学习 《python运维脚本》: python运维脚本实践 《shell》:shell学习 《terraform》持续更新中:terraform_Aws学习零基础入门到最佳实战 《k8…...
本地服务器物理机中redis设置、取消密码
1.服务器物理机上redis的操作【服务器中操作】 (1)首先先看一下当前运行中的redis实例: [rootiZuf67k70ucx14s6zcv54dZ var]# ps aux | grep redis-server因为我这里有两个实例在运行,即物理机上的redis和docker中的redis&…...
关于xilinx的FFTIP的使用和仿真
工具:vivado2018.3,modelsim10.6d 场景:在进行数据进行频谱分析的时候,使用FPGA来完成FFT的计算可以加快数据的计算速度。 下面使用仿真完成DDS产生的数据的FFT以及IFFT。原始数据使用DDSIP产生,通过IP产生的波形数据…...
ant design pro 如何去保存颜色
上图 就是实现这样的效果 后端是这样的,这个颜色肯定是存到字符串里的 这是第一步 import mongoose, { Schema, Document } from mongoose;interface IDiscountCard extends Document {title: string;subtitle: string;image: string;shopUrl: string;bgColor: s…...
【Hadoop】建立圈内组件的宏观认识
01存储02计算03调度04其他05回忆 众多组件们构建了大规模分布式计算和存储平台。本文介绍Hadoop生态圈中各个组件的主要功能和作用,辅助学者理解每个组件的定位和用途,从而建立对圈内组件的宏观认识。梳理清楚HDFS、MapReduce、YARN、Hive、HBase、Spark…...
C++:命名空间与输入输出
目录 前言 一、命名空间 1.1 namespace的价值 1.2 namespace的定义 1.3 命名空间的使用 二、C输入&输出 前言 C是一种面向对象的计算机程序设计语言,它扩展了C语言的功能,并引入了面向对象编程的概念,如类、继承和多态等&a…...
Azure DevOps Server 数据库日志已满,TF30042: The database is full
Contents 1. 问题描述2. 处理方式 2.1 系统备份2.2 收缩日志2.3 恢复模式2.4 日志增长无法控制 1. 问题描述 Azure DevOps Server 作为微软的软件开发管理平台产品,理所当然地使用了微软的数据库软件SQL Server。 在一个大型的开发团队中,Azure DevOps S…...
[C#]OpenCvSharp 实现Bitmap和Mat的格式相互转换
//转为 bitmap方法一: Bitmap map OpenCvSharp.Extensions.BitmapConverter.ToBitmap(mat); process_pictureBox.Image map; //转为 bitmap方法二: Bitmap map new Bitmap(mat.ToMemoryStream()); process_pictureBox.Image map; //Image img 转为…...
【区块链+金融服务】基于区块链的供应链金融系统 | FISCO BCOS应用案例
传统供应链金融存在着信息不对称、信任问题和繁琐流程等弊端。为了解决这些问题,京北方搭建了基于区块链 的供应链金融系统,提供了更高效、透明、安全和可信的交易环境。 系 统 采 用 FISCO BCOS 为 底 层 链, 技 术 栈 使 用 Java 语 言 进…...
AI语言大模型商业价值深度解析
点击蓝字 关注我 随着人工智能(AI)技术的飞速发展,特别是深度学习算法的进步,AI语言大模型在自然语言处理领域的表现日益突出。国内外多种语言大模型如:OpenAi 的 ChatGpt,阿里通义千问,百度文心…...
理解DDD领域驱动设计思想
一、引言 在软件开发的广袤领域中,领域驱动设计(Domain-Driven Design,简称 DDD)犹如一颗璀璨的明星,备受瞩目。对于期望运用 DDD 开展项目的研发人员而言,明晰 DDD 的本质是实现其有效应用的基石。需注意…...
音频剪辑软件哪个好用?五大音频剪辑软件分享
如果你正打算在家自学视频制作,那么恭喜你,你已经踏上了一段充满魔法与惊喜的旅程!不过,别忘了,视频的灵魂不仅仅在于画面,更在于那直击心灵的音效。 想象一下,一个精心剪辑的片段,…...
12.2 使用prometheus-sdk向pushgateway打点
本节重点介绍 : 使用golang sdk打prometheus4种指标,推送到pushgateway gauge、counter、histogram、summary的初始化4种类似的设置值的方法推送到pushgateway的方法 prometheus配置采集pushgateway,grafana上配大盘 golang-sdk 项目地址 https://git…...
HTTPS 详解
HTTPS 是以安全为目标的 HTTP 通道,它在 HTTP 中加入 SSL 层以提高数据传输的安全性。HTTP 被用于在 Web 浏览器和网站服务器之间传递信息,但以明文形式发送内容,不提供任何方式的数据加密,如果攻击者截取了 Web 浏览器和网站服务…...
Microsoft Edge 使用方法与秘诀概览
目录 编辑引言 Microsoft Edge 功能与技巧概览 掌握这些设置技巧,让 Edge 浏览器的体验更干净 1. 使用阅读视图 2. 开启广告过滤 3. 管理扩展 4. 个性化新标签页 5. 使用网页截图 6. 清理浏览器缓存 7. 管理启动设置 8. 自定义地址栏建议 9. 使用内置笔…...
【视频】onvif、RTP、RTCP、SDP、RTSP、gb21818区别
ONVIF (Open Network Video Interface Forum): ONVIF是一个全球性的开放网络视频接口论坛,致力于发展基于IP网络的物联网设备的标准化。它提供了一个通用的标准接口,使不同厂商生产的网络视频产品能够互相兼容。 RTP (Real-time Transport Protocol): R…...
8-4 循环神经网络
对于 (8.4.2)中的函数 f f f,隐变量模型不是近似值。 毕竟 h t h_{t} ht是可以仅仅存储到目前为止观察到的所有数据, 然而这样的操作可能会使计算和存储的代价都变得昂贵。 回想一下,我们在前面讨论过的具有隐藏单元的隐藏层。 值得注意的…...
Linux系统编程 --- 多线程
线程:是进程内的一个执行分支,线程的执行粒度,要比进程要细。 一、线程的概念 1、Linux中线程该如何理解 地址空间就是进程的资源窗口。 在一个程序里的一个执行路线就叫做线程(thread)。更准确的定义是࿱…...
Grafana中的rate与irate以及histogram
用法 rate rate函数用于计算一个时间序列在给定时间范围内的平均速率。它对每个数据点进行线性插值来计算速率,因此对于平滑和稳定的数据来说,rate是一个不错的选择。语法如下: rate(metric_name[time_range])metric_name: 指标名称。time…...
什么是网络安全态势感知
态势感知是一种基于环境的、动态、整体地洞悉安全风险的能力,是以安全大数据为基础,从全局视角提升对安全威胁的发现识别、理解分析、响应处置能力的一种方式、最终是为了决策与行动,是安全能力的落地 态势感知的重要性 随着网络与信息技术的…...
php 在app中唤起微信app进行支付,并处理回调通知
<?phpnamespace app\api\controller;use think\facade\Db; use think\facade\Log;class Wxzf {...
高效同步与处理:ADTF流服务在自动驾驶数采中的应用
目录 一、ADTF 流服务 1、流服务源(Streaming Source) 2、流服务汇(Streaming Sink) 二、数据链路 1、数据管道(Data Pipe) 2、子流(Substreams) 3、触发管道(Tri…...
【Arduino】ATmega328PB 连接 LSM6DS3 姿态传感器,并读数据(不确定 ESP 系列是否可行,但大概率是可行的)
总览 1.初始化 ATmega328PB,默认大家已经完成了 328 的配置准备工作,已经直接能够向里面写入程序 2.接线,然后验证 mega328 的 I2C 设备接口能否扫描到 LSM6DS3 3.编写代码,上传,查看串口数据。完成。 一、初始化 AT…...
live2d + edge-tts 优雅的实现数字人讲话 ~
震惊!live2d数字人竟开口说话 ~ 之前有想做数字人相关项目,查了一些方案。看了一些三方大厂的商用方案,口型有点尴尬,而且很多是采用视频流的方案,对流量的消耗很大。后来了解了live2d 技术,常在博客网页上…...
二进制安装php
下载php二进制包: 官网地址:https://www.php.net/releases/ PHP: Releaseshttps://www.php.net/releases/在里边可以选择自己要下载的包进行下载; 下载完成后进行解压: tar xvzf php-7.3.12.tar.gz 解压后 进入目录进行预编…...
旧版Pycharm支持的python版本记录
版权声明:本文为博主原创文章,如需转载请贴上原博文链接:旧版Pycharm支持的python版本记录-CSDN博客 前言:近期由于打算研究GitHub上一个开源量化交易平台开发框架,但是该框架是基于python3.10的版本开发,所…...
java实现七牛云内容审核功能,文本、图片和视频的内容审核(鉴黄、鉴暴恐、敏感人物)
目录 1、七牛云内容审核介绍 2、查看内容审核官方文档 2.1、文本内容审核 2.1.1、文本内容审核的请求示例 2.1.2、文本内容审核的返回示例 2.2、图片内容审核 2.2.1、请求参数 2.2.2、返回参数 2.3、视频内容审核 3、代码实现 3.1、前期代码准备 3.2、文本内容审核…...
C++面试基础系列-struct
系列文章目录 文章目录 系列文章目录C面试基础系列-struct1.C中struct2.C中struct2.1.同名函数2.2.typedef定义结构体别名2.3.继承 3.总结3.1.C和C中的Struct区别 4.struct字节对齐5.struct与const 关于作者 C面试基础系列-struct 1.C中struct struct里面只能放数据类型&#…...