












//D:\C\WpfApp12\NumUpDown.cs using System; using System.Collections.Generic; using System.Text; 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 WpfApp12 { /// <summary> /// Follow steps 1a or 1b and then 2 to use this custom control in a XAML file. /// /// Step 1a) Using this custom control in a XAML file that exists in the current project. /// Add this XmlNamespace attribute to the root element of the markup file where it is /// to be used: /// /// xmlns:MyNamespace="clr-namespace:WpfApp12" /// /// /// Step 1b) Using this custom control in a XAML file that exists in a different project. /// Add this XmlNamespace attribute to the root element of the markup file where it is /// to be used: /// /// xmlns:MyNamespace="clr-namespace:WpfApp12;assembly=WpfApp12" /// /// You will also need to add a project reference from the project where the XAML file lives /// to this project and Rebuild to avoid compilation errors: /// /// Right click on the target project in the Solution Explorer and /// "Add Reference"->"Projects"->[Browse to and select this project] /// /// /// Step 2) /// Go ahead and use your control in the XAML file. /// /// <MyNamespace:NumUpDown/> /// /// </summary> public class NumUpDown : Control { private Button upBtn, downBtn; static NumUpDown() { DefaultStyleKeyProperty.OverrideMetadata(typeof(NumUpDown), new FrameworkPropertyMetadata(typeof(NumUpDown))); } public override void OnApplyTemplate() { base.OnApplyTemplate(); var tempUpBtn = GetTemplateChild("PART_UpBtn") as Button; if (tempUpBtn != null) { upBtn = tempUpBtn; upBtn.Click += UpBtn_Click; } var tempDownBtn = GetTemplateChild("PART_DownBtn") as Button; if (tempDownBtn != null) { downBtn = tempDownBtn; downBtn.Click += DownBtn_Click; } } private void DownBtn_Click(object sender, RoutedEventArgs e) { if (--Num < MinNum) { Num = MaxNum; } NumStr = $"{Num:D2}"; } private void UpBtn_Click(object sender, RoutedEventArgs e) { if (++Num > MaxNum) { Num = MinNum; } NumStr = $"{Num:D2}"; } public int Num { get { return (int)GetValue(NumProperty); } set { SetValue(NumProperty, value); } } // Using a DependencyProperty as the backing store for Num. This enables animation, styling, binding, etc... public static readonly DependencyProperty NumProperty = DependencyProperty.Register(nameof(Num), typeof(int), typeof(NumUpDown), new PropertyMetadata(0, OnNumChanged)); private static void OnNumChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { } public int MaxNum { get { return (int)GetValue(MaxNumProperty); } set { SetValue(MaxNumProperty, value); } } // Using a DependencyProperty as the backing store for MaxNum. This enables animation, styling, binding, etc... public static readonly DependencyProperty MaxNumProperty = DependencyProperty.Register(nameof(MaxNum), typeof(int), typeof(NumUpDown), new PropertyMetadata(0)); public int MinNum { get { return (int)GetValue(MinNumProperty); } set { SetValue(MinNumProperty, value); } } // Using a DependencyProperty as the backing store for MinNum. This enables animation, styling, binding, etc... public static readonly DependencyProperty MinNumProperty = DependencyProperty.Register(nameof(MinNum), typeof(int), typeof(NumUpDown), new PropertyMetadata(0)); public string NumStr { get { return (string)GetValue(NumStrProperty); } set { SetValue(NumStrProperty, value); } } // Using a DependencyProperty as the backing store for NumStr. This enables animation, styling, binding, etc... public static readonly DependencyProperty NumStrProperty = DependencyProperty.Register(nameof(NumStr), typeof(string), typeof(NumUpDown), new PropertyMetadata("00")); public string ControlName { get { return (string)GetValue(ControlNameProperty); } set { SetValue(ControlNameProperty, value); } } // Using a DependencyProperty as the backing store for ControlName. This enables animation, styling, binding, etc... public static readonly DependencyProperty ControlNameProperty = DependencyProperty.Register(nameof(ControlName), typeof(string), typeof(NumUpDown), new PropertyMetadata("")); } } //D:\C\WpfApp12\TimePicker.cs using System; using System.Collections.Generic; using System.Text; 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 WpfApp12 { /// <summary> /// Follow steps 1a or 1b and then 2 to use this custom control in a XAML file. /// /// Step 1a) Using this custom control in a XAML file that exists in the current project. /// Add this XmlNamespace attribute to the root element of the markup file where it is /// to be used: /// /// xmlns:MyNamespace="clr-namespace:WpfApp12" /// /// /// Step 1b) Using this custom control in a XAML file that exists in a different project. /// Add this XmlNamespace attribute to the root element of the markup file where it is /// to be used: /// /// xmlns:MyNamespace="clr-namespace:WpfApp12;assembly=WpfApp12" /// /// You will also need to add a project reference from the project where the XAML file lives /// to this project and Rebuild to avoid compilation errors: /// /// Right click on the target project in the Solution Explorer and /// "Add Reference"->"Projects"->[Browse to and select this project] /// /// /// Step 2) /// Go ahead and use your control in the XAML file. /// /// <MyNamespace:TimePicker/> /// /// </summary> public class TimePicker : Control { static TimePicker() { DefaultStyleKeyProperty.OverrideMetadata(typeof(TimePicker), new FrameworkPropertyMetadata(typeof(TimePicker))); } public override void OnApplyTemplate() { base.OnApplyTemplate(); } public int HourNum { get { return (int)GetValue(HourNumProperty); } set { SetValue(HourNumProperty, value); } } // Using a DependencyProperty as the backing store for HourNum. This enables animation, styling, binding, etc... public static readonly DependencyProperty HourNumProperty = DependencyProperty.Register(nameof(HourNum), typeof(int), typeof(TimePicker), new PropertyMetadata(0,OnHourNumChanged)); private static void OnHourNumChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var tmPicker=d as TimePicker; if(tmPicker!=null) { tmPicker.TimeStr = $"{tmPicker.HourNum:D2}:{tmPicker.MinuteNum:D2}:{tmPicker.SecondNum:D2}"; } } public int MinuteNum { get { return (int)GetValue(MinuteNumProperty); } set { SetValue(MinuteNumProperty, value); } } // Using a DependencyProperty as the backing store for MinuteNum. This enables animation, styling, binding, etc... public static readonly DependencyProperty MinuteNumProperty = DependencyProperty.Register(nameof(MinuteNum), typeof(int), typeof(TimePicker), new PropertyMetadata(0,OnMinuteNumChanged)); private static void OnMinuteNumChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var tmPicker = d as TimePicker; if (tmPicker != null) { tmPicker.TimeStr = $"{tmPicker.HourNum:D2}:{tmPicker.MinuteNum:D2}:{tmPicker.SecondNum:D2}"; } } public int SecondNum { get { return (int)GetValue(SecondNumProperty); } set { SetValue(SecondNumProperty, value); } } // Using a DependencyProperty as the backing store for SecondNum. This enables animation, styling, binding, etc... public static readonly DependencyProperty SecondNumProperty = DependencyProperty.Register(nameof(SecondNum), typeof(int), typeof(TimePicker), new PropertyMetadata(0, OnSecondNumChanged)); private static void OnSecondNumChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var tmPicker = d as TimePicker; if (tmPicker != null) { tmPicker.TimeStr = $"{tmPicker.HourNum:D2}:{tmPicker.MinuteNum:D2}:{tmPicker.SecondNum:D2}"; } } public string TimeStr { get { return (string)GetValue(TimeStrProperty); } set { SetValue(TimeStrProperty, value); } } // Using a DependencyProperty as the backing store for TimeStr. This enables animation, styling, binding, etc... public static readonly DependencyProperty TimeStrProperty = DependencyProperty.Register(nameof(TimeStr), typeof(string), typeof(TimePicker), new PropertyMetadata("00:00:00")); } } //D:\C\WpfApp12\Themes\Generic.xaml <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:WpfApp12"> <Style TargetType="{x:Type local:NumUpDown}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type local:NumUpDown}"> <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"> <Grid Width="90" Height="70"> <Grid.Resources> <Style TargetType="TextBlock"> <Setter Property="HorizontalAlignment" Value="Center"/> <Setter Property="TextAlignment" Value="Center"/> <Setter Property="VerticalAlignment" Value="Center"/> <Setter Property="FontSize" Value="20"/> </Style> </Grid.Resources> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition/> <RowDefinition/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="3*"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <TextBlock Grid.Row="1" Grid.Column="0" HorizontalAlignment="Right" Text="{Binding Path=ControlName,RelativeSource={RelativeSource AncestorType={x:Type local:NumUpDown}}}"/> <Button x:Name="PART_UpBtn" Grid.Row="0" Grid.Column="1" ToolTip="{Binding Path=MaxNum,RelativeSource={RelativeSource AncestorType={x:Type local:NumUpDown}}}"> <Path Data="M0,8 L8,0 L16,8 Z" Fill="Black" Width="10" Height="10" Stretch="Uniform"/> </Button> <TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding Path=NumStr,RelativeSource={RelativeSource AncestorType={x:Type local:NumUpDown}}}"/> <Button x:Name="PART_DownBtn" Grid.Row="2" Grid.Column="1" ToolTip="{Binding Path=MinNum,RelativeSource={RelativeSource AncestorType={x:Type local:NumUpDown}}}"> <Path Data="M0,0 L8,8 L16,0 Z" Fill="Black" Width="10" Height="10" Stretch="Uniform"/> </Button> </Grid> </Border> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style TargetType="{x:Type local:TimePicker}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type local:TimePicker}"> <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"> <Grid Height="110" Width="300"> <Grid.Resources> <Style TargetType="TextBlock"> <Setter Property="HorizontalAlignment" Value="Center"/> <Setter Property="VerticalAlignment" Value="Center"/> <Setter Property="FontSize" Value="30"/> </Style> </Grid.Resources> <Grid.RowDefinitions> <RowDefinition Height="*"/> <RowDefinition Height="3*"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition/> <ColumnDefinition/> </Grid.ColumnDefinitions> <TextBlock Grid.Row="0" Grid.Column="0" Text="Time:"/> <TextBlock Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="2" Text="{Binding Path=TimeStr,RelativeSource={RelativeSource AncestorType={x:Type local:TimePicker}}}"/> <local:NumUpDown MaxNum="23" MinNum="0" ControlName="Hour:" Grid.Row="1" Grid.Column="0" Num="{Binding Path=HourNum,Mode=TwoWay,RelativeSource={RelativeSource AncestorType={x:Type local:TimePicker}}}"/> <local:NumUpDown MaxNum="59" MinNum="0" ControlName="Minute:" Grid.Row="1" Grid.Column="1" Num="{Binding Path=MinuteNum,Mode=TwoWay,RelativeSource={RelativeSource AncestorType={x:Type local:TimePicker}}}"/> <local:NumUpDown MaxNum="59" MinNum="0" ControlName="Second:" Grid.Row="1" Grid.Column="2" Num="{Binding Path=SecondNum,Mode=TwoWay,RelativeSource={RelativeSource AncestorType={x:Type local:TimePicker}}}"/> </Grid> </Border> </ControlTemplate> </Setter.Value> </Setter> </Style> </ResourceDictionary> //D:\C\WpfApp12\MainWindow.xaml <Window x:Class="WpfApp12.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:WpfApp12" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800"> <Grid> <StackPanel Height="100" Width="300" Orientation="Horizontal"> <local:TimePicker/> </StackPanel> </Grid> </Window>
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。