精华内容
下载资源
问答
  • wpf时间控件带时分秒

    2018-12-14 11:12:06
    wpf时间控件带时分秒的显示,支持mvvm,源码中带封装好的类库和调用的demo,用起来十分方便
  • WPF 时间控件重写

    2016-04-06 15:07:39
    1.完成手动设置、点击控件设置时间; 2.支持时间获取方法及赋值方法; 3.完成时间控件显示控制; 难点就是重写思路,知道方法重写很简单的,所以8分是你实在不知道的情况下你送我的
  • 基于Toolkit ui组件进行的style 修改,这是一个比较酷的样式效果,也可以让朋友们知道怎么修改xctk:DateTimePicker 的样式,这个 Toolkit 可以在nuget 上直接安装,我在包了也放置了Toolkit 的源代码,并修复了它的...
  • 不需要日,因此需要对原有的DatePicker进行修改,查询了网上的内容,最终从一篇帖子里看到了添加附加属性的方法,地址是http://stackoverflow.com/questions/1798513/wpf-toolkit-datepicker-month-year-only ...

    最近的项目,查询时只需要年和月,不需要日,因此需要对原有的DatePicker进行修改,查询了网上的内容,最终从一篇帖子里看到了添加附加属性的方法,地址是http://stackoverflow.com/questions/1798513/wpf-toolkit-datepicker-month-year-only

    原文是用了两个类,其中一个是为了让DatePicker下的Calendar只显示年月,不显示日,另一个类是为了让DatePicker格式化为yyyy-MM格式,但是从文章中可以看出,有人提出了,用格式化类进行格式化时,DatePicker控件会闪动一下,当然不影响使用。如果不想使用文章中提到的类进行格式化,也可以用我上一篇文章中的方法进行格式化,不会出现闪动的情况。

    只显示年月的类

    复制代码
     public class DatePickerCalendar
        {
            public static readonly DependencyProperty IsMonthYearProperty =
            DependencyProperty.RegisterAttached("IsMonthYear", typeof(bool), typeof(DatePickerCalendar),
                                                new PropertyMetadata(OnIsMonthYearChanged));
    
            public static bool GetIsMonthYear(DependencyObject dobj)
            {
                return (bool)dobj.GetValue(IsMonthYearProperty);
            }
    
            public static void SetIsMonthYear(DependencyObject dobj, bool value)
            {
                dobj.SetValue(IsMonthYearProperty, value);
            }
    
            private static void OnIsMonthYearChanged(DependencyObject dobj, DependencyPropertyChangedEventArgs e)
            {
                var datePicker = (DatePicker)dobj;
    
                Application.Current.Dispatcher
                    .BeginInvoke(DispatcherPriority.Loaded,
                                 new Action<DatePicker, DependencyPropertyChangedEventArgs>(SetCalendarEventHandlers),
                                 datePicker, e);
            }
    
            private static void SetCalendarEventHandlers(DatePicker datePicker, DependencyPropertyChangedEventArgs e)
            {
                if (e.NewValue == e.OldValue)
                    return;
    
                if ((bool)e.NewValue)
                {
                    datePicker.CalendarOpened += DatePickerOnCalendarOpened;
                    datePicker.CalendarClosed += DatePickerOnCalendarClosed;
                }
                else
                {
                    datePicker.CalendarOpened -= DatePickerOnCalendarOpened;
                    datePicker.CalendarClosed -= DatePickerOnCalendarClosed;
                }
            }
    
            private static void DatePickerOnCalendarOpened(object sender, RoutedEventArgs routedEventArgs)
            {
                var calendar = GetDatePickerCalendar(sender);
                calendar.DisplayMode = CalendarMode.Year;
    
                calendar.DisplayModeChanged += CalendarOnDisplayModeChanged;
            }
    
            private static void DatePickerOnCalendarClosed(object sender, RoutedEventArgs routedEventArgs)
            {
                var datePicker = (DatePicker)sender;
                var calendar = GetDatePickerCalendar(sender);
                datePicker.SelectedDate = calendar.SelectedDate;
    
                calendar.DisplayModeChanged -= CalendarOnDisplayModeChanged;
            }
    
            private static void CalendarOnDisplayModeChanged(object sender, CalendarModeChangedEventArgs e)
            {
                var calendar = (Calendar)sender;
                if (calendar.DisplayMode != CalendarMode.Month)
                    return;
    
                calendar.SelectedDate = GetSelectedCalendarDate(calendar.DisplayDate);
    
                var datePicker = GetCalendarsDatePicker(calendar);
                datePicker.IsDropDownOpen = false;
            }
    
            private static Calendar GetDatePickerCalendar(object sender)
            {
                var datePicker = (DatePicker)sender;
                var popup = (Popup)datePicker.Template.FindName("PART_Popup", datePicker);
                return ((Calendar)popup.Child);
            }
    
            private static DatePicker GetCalendarsDatePicker(FrameworkElement child)
            {
                var parent = (FrameworkElement)child.Parent;
                if (parent.Name == "PART_Root")
                    return (DatePicker)parent.TemplatedParent;
                return GetCalendarsDatePicker(parent);
            }
    
            private static DateTime? GetSelectedCalendarDate(DateTime? selectedDate)
            {
                if (!selectedDate.HasValue)
                    return null;
                return new DateTime(selectedDate.Value.Year, selectedDate.Value.Month, 1);
            }
        }
    复制代码
    DatePickerCalendar

    调用方式

    <DatePicker Width="200" Height="30" local:DatePickerCalendar.IsMonthYear="True"/>

    展示效果

    从图上就能看到左右不一样,左侧的是添加附加属性的,点击以后直接显示月,后侧没用的则显示到日,虽然都格式化为了yyyy-MM,但是Calendar如果显示到日的话,用户体验不好。

    ========================================================================================================================

    2015年8月4日 记:

    今天在项目中发现一个问题,就是采用我上一篇帖子中的三句话进行DatePicker时间的格式化显示,但是由于用的是Thread,所以是在线程里进行格式化的,因此,影响到了同事做的其他模块,因为大部分都是格式化为yyyy-MM-dd,但是由于我的一个页面是格式化为了yyyy-MM,而其中的一个同事并没有在他的构造函数里使用三句格式化他的DatePicker,从而导致他其他的时间计算出现问题,因此在保证原有功能不变的情况下,需要显示yyyy-MM,就需要用到原帖子中的另一个类。

    DatePickerDateFormat

    复制代码
    public class DatePickerDateFormat
        {
            public static readonly DependencyProperty DateFormatProperty =
    DependencyProperty.RegisterAttached("DateFormat", typeof(string), typeof(DatePickerDateFormat),
                                        new PropertyMetadata(OnDateFormatChanged));
    
            public static string GetDateFormat(DependencyObject dobj)
            {
                return (string)dobj.GetValue(DateFormatProperty);
            }
    
            public static void SetDateFormat(DependencyObject dobj, string value)
            {
                dobj.SetValue(DateFormatProperty, value);
            }
    
            private static void OnDateFormatChanged(DependencyObject dobj, DependencyPropertyChangedEventArgs e)
            {
                var datePicker = (DatePicker)dobj;
    
                Application.Current.Dispatcher.BeginInvoke(
                    DispatcherPriority.Loaded, new Action<DatePicker>(ApplyDateFormat), datePicker);
            }
    
            private static void ApplyDateFormat(DatePicker datePicker)
            {
                var binding = new Binding("SelectedDate")
                {
                    RelativeSource = new RelativeSource { AncestorType = typeof(DatePicker) },
                    Converter = new DatePickerDateTimeConverter(),
                    ConverterParameter = new Tuple<DatePicker, string>(datePicker, GetDateFormat(datePicker))
                };
                var textBox = GetTemplateTextBox(datePicker);
                textBox.SetBinding(TextBox.TextProperty, binding);
    
                textBox.PreviewKeyDown -= TextBoxOnPreviewKeyDown;
                textBox.PreviewKeyDown += TextBoxOnPreviewKeyDown;
    
                datePicker.CalendarOpened -= DatePickerOnCalendarOpened;
                datePicker.CalendarOpened += DatePickerOnCalendarOpened;
            }
    
            private static TextBox GetTemplateTextBox(Control control)
            {
                control.ApplyTemplate();
                return (TextBox)control.Template.FindName("PART_TextBox", control);
            }
    
            private static void TextBoxOnPreviewKeyDown(object sender, KeyEventArgs e)
            {
                if (e.Key != Key.Return)
                    return;
    
                /* DatePicker subscribes to its TextBox's KeyDown event to set its SelectedDate if Key.Return was
                 * pressed. When this happens its text will be the result of its internal date parsing until it
                 * loses focus or another date is selected. A workaround is to stop the KeyDown event bubbling up
                 * and handling setting the DatePicker.SelectedDate. */
    
                e.Handled = true;
    
                var textBox = (TextBox)sender;
                var datePicker = (DatePicker)textBox.TemplatedParent;
                var dateStr = textBox.Text;
                var formatStr = GetDateFormat(datePicker);
                datePicker.SelectedDate = DatePickerDateTimeConverter.StringToDateTime(datePicker, formatStr, dateStr);
            }
    
            private static void DatePickerOnCalendarOpened(object sender, RoutedEventArgs e)
            {
                /* When DatePicker's TextBox is not focused and its Calendar is opened by clicking its calendar button
                 * its text will be the result of its internal date parsing until its TextBox is focused and another
                 * date is selected. A workaround is to set this string when it is opened. */
    
                var datePicker = (DatePicker)sender;
                var textBox = GetTemplateTextBox(datePicker);
                var formatStr = GetDateFormat(datePicker);
                textBox.Text = DatePickerDateTimeConverter.DateTimeToString(formatStr, datePicker.SelectedDate);
            }
    
            private class DatePickerDateTimeConverter : IValueConverter
            {
                public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
                {
                    var formatStr = ((Tuple<DatePicker, string>)parameter).Item2;
                    var selectedDate = (DateTime?)value;
                    return DateTimeToString(formatStr, selectedDate);
                }
    
                public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
                {
                    var tupleParam = ((Tuple<DatePicker, string>)parameter);
                    var dateStr = (string)value;
                    return StringToDateTime(tupleParam.Item1, tupleParam.Item2, dateStr);
                }
    
                public static string DateTimeToString(string formatStr, DateTime? selectedDate)
                {
                    return selectedDate.HasValue ? selectedDate.Value.ToString(formatStr) : null;
                }
    
                public static DateTime? StringToDateTime(DatePicker datePicker, string formatStr, string dateStr)
                {
                    DateTime date;
                    var canParse = DateTime.TryParseExact(dateStr, formatStr, CultureInfo.CurrentCulture,
                                                          DateTimeStyles.None, out date);
    
                    if (!canParse)
                        canParse = DateTime.TryParse(dateStr, CultureInfo.CurrentCulture, DateTimeStyles.None, out date);
    
                    return canParse ? date : datePicker.SelectedDate;
                }
            }
        }
    复制代码
    DatePickerDateFormat

    总的调用方法 

    <DatePicker conver:DatePickerCalendar.IsMonthYear="True" conver:DatePickerDateFormat.DateFormat="yyyy-MM" />

    转载于:https://www.cnblogs.com/jinxiaobao7n/p/4760631.html

    展开全文
  • 连接 转载于:https://www.cnblogs.com/m7777/p/4667670.html

    连接

    转载于:https://www.cnblogs.com/m7777/p/4667670.html

    展开全文
  • wpf 时间控件

    2017-06-29 12:18:56
    wpf 时间控件
  • WPF日期时间控件

    2018-09-05 09:12:45
    WPF日期时间控件,可选择日期和时间。日期时间格式自定义,用yyyy-MM-dd HH:mm:ss这样的字符串定义格式。有源代码。
  • WPF时间控件

    2021-04-06 15:53:54
    WPF时间轴 在Flash动画的制作中,有一个时间轴的概念。时间轴是用来控制在动画运行中相应的时间时,某个或某些对象所需要执行的操作。
  • WPF自带的控件中只有Datepicker这个控件,不足以满足功能,鉴于WPF强大的自定义控件Usercontrol的功能,所以修改了一个支持选择日期时间控件---DateTimePicker,
  • WPF分页控件

    千次阅读 2019-06-17 19:44:11
    WPF分页控件 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 开发工具与关键技术:C#,WPF 作者:刘海红 撰写时间: 2019年6月12日 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~...

    WPF分页控件

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    开发工具与关键技术:C#,WPF

    作者:刘海红

    撰写时间: 2019年6月12日

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    以前的分页按钮都是用插件来完成的,只需要引用插件就可以用了,但是在WPF中的分页是没有插件的,都是要自己去写和封装的。而我们的WPF的分页用到的是几个控件来实现的页面布局,所以我们也需要初始化这个分页,可以看到下图红色框中的下拉框,它是可以显示所有行数据提供用户选择的,一页有多少行,这个下拉框呢我们可以人为绑定下拉框,绑定我们的数据。

     

    可以看一下如下图中的分页的页面布局代码:

    在页面加载事件中加入了当前页面的页数,并且它的最大页数是多少,甚至分页下拉框的显示多少行值用来绑定每页行数的下框

    txtCurrentPage.Text = "0";//当前页数

    lblMaxPage.Content = decPageCount;//最大页数

    int[] intPageLineCounts = { 17, 34, 51, 68, 85, 102 };//创建int数组

    cboPageLineCount.ItemsSource = intPageLineCounts;//绑定每页行数下拉框

    cboPageLineCount.Text = intPageSize.ToString();//设置默认值

    在绑定之前我们要初始化一下全局变量并且用到linq语句查询分页,它也相当于我们sql语句,我们得到是一个字符串紧接着我们用linq语句,根据外界连接,接着我们需要一个排序的字段,为什么要进行排序呢?因为我们等一下要进行分页,要进行分页我们就需要知道有几种可能实现分页?第一种:要知道开始索引,结束索引;第二种:知道开始索引也要知道每一页的条数,以前MVC知道的就是第二种情况。

    我们这里的分页操作专门封装到了一个位置里面,首先我们封装一个方法,第一个就是控制按钮的样式,意思就是什么时候该显示按钮什么时候不该显示按钮,不能够点击。以此类推方法都是一样的。

    点击上一页和下一页的方法,控制首页的按钮,找到我们的首页给它点击按钮事件,在事件里面控制我们的控件,当它等于1的时候说明它可以用

    每一次的方法都会调用到查询,所以我们需要在页面布局中找到查询的事件,并且写出查询的方法,这里查询方法把返回的值赋给了DGV,

    查询数据的方法,我们分页的目的就是为了得到后面表格的一个数据,所以我们这里需要注意一下的,它是有返回值的,返回的是一个表格,所以我们直接声明一个方法,在下图代码中我们看到了定义一个方法用来分页的,因为我们返回的数据是一个表格是的数据,返回部分的数据,所以这里返回DataTable

    现在我们需要去到服务端进行封装一个公共分页查询的方法,我们创建一个类,这个就叫做PublicFunction,这个名字你可以自己取,但是要和客户端对应,PublicPagingSelect是数据库中的存储过程。这里的方法我们就封装好了,得到的就是Data数据,这个方法是执行哪一个方法的分页,写完后配置一下服务。

    数据库存储过程。

    总结:分页过程是很复杂,它不像MVC那样引用一个分页插件,用table标签中的bsgrid来获取数据就可以了。WPF中的分页数据要进行多个步骤。页面布局,后台代码,数据库存储,服务端代码,配置文件…这些都是要经历过的过程。

    展开全文
  • WPF时间扩展控件 支持 日期+时分秒,可以选择和设置当前时间,具体到秒.
  • WPF时间扩展控件,能够显示时分秒
  • WPF日期控件模板重写

    2020-03-19 17:11:02
    该项目重写了WPF中的日期控件,选择当前日期,过去日期,可选日期,整体界面重新重写。另一个项目带有滚动时间,按像素点滚动。
  • 系列文章目录 前言 WPF自定义控件和样式教程-自己的控件库(简介) 第一章 WPF自定义控件和样式教程-自己的控件库(一)...很可惜,WPF自带的时间控件要不然只支持年月日,要不然只支持时分秒。好吧,拿我就两个...

     

    系列文章目录

           前言 WPF自定义控件和样式教程-自己的控件库(简介)

           第一章 WPF自定义控件和样式教程-自己的控件库(一)-时间选择器TimePick


    目录

    前言

    一、构思

    二、UI设计

    1.时间展示和开始选择按钮

    2.下拉Popup

    第一部分-年月选择

    第二部分-Day的选择

    第三部分-时分秒

    第四部分-重置与确定

    三、后台逻辑

    总结


     


    前言

    相信很多WPF从业者和我一样,都遇到过一个问题:我想要一个能同时选择年月日和时分秒的控件。

    很可惜,WPF自带的时间控件要不然只支持年月日,要不然只支持时分秒。好吧,拿我就两个结合起来用,用着用着问题又来了:自带的控件怎么看怎么不顺眼,样式还不好调整。随着界面制作越来越追求美观和差异化,在项目中直接使用自带的控件就像野马装了个金杯面包车的车门一样别扭。

    那么,我们为什么不自己制作一个又能编辑年月日,又能编辑时分秒的控件呢?

    一、构思

    首先,我们参考一下WIN10的日历。

    这个日历主要展示了时间中的年月日,我们可以参考这个来设计我们自己的控件。至于时分秒,我们就用最常见的 "XX 时 XX 分 XX秒" 来设计把。下面是我自己设计的一个简单的时间选择器。

     

    二、UI设计

    要想达到上图所示的效果,我们得先用系统自带的控件布好局。下面是控件的Xaml代码。

    <UserControl x:Class="Why_Wpf_UserControls.TimePick"
                 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:Why_Wpf_UserControls"
                 mc:Ignorable="d" 
                  MinWidth="200" MaxWidth="400" MinHeight="22" MaxHeight="30">
    <UserControl.Resources>
            <ResourceDictionary Source="Resource/Themes/Dictionary.xaml" />
     </UserControl.Resources>
    <Grid Background="#FF122132">
            <Grid.Resources>
                <Style TargetType="RadioButton" BasedOn="{StaticResource DayRadioButton}"/>
                <Style TargetType="{x:Type TextBox}" >
                    <Setter Property="Background" Value="#FF172E4D" />
                    <Setter Property="BorderBrush" Value="#FFEAEAEA" />
                    <Setter Property="BorderThickness" Value="0" />
                    <Setter Property="Foreground" Value="#96bfd6" />
                </Style>
                <Style TargetType="{x:Type Label}">
                    <Setter Property="Foreground" Value="#96bfd6" />
                    <Setter Property="FontSize" Value="14" />
                </Style>
                <Style TargetType="Button">
                    <Style.Triggers>
                        <Trigger Property="Button.IsEnabled" Value="False">
                            <Setter Property="Opacity" Value="0.5" />
                        </Trigger>
                        <Trigger Property="Button.IsMouseOver" Value="True">
                            <Setter Property="Opacity" Value="0.7" />
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </Grid.Resources>
            <Border Background="Transparent"  >
                <WrapPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center" >
                    <StackPanel Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Center" >
                        <ToggleButton  x:Name="btn_ChoseTime" Content="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:TimePick}}, Path=TimeValue, Converter={StaticResource DateToString}}" Width="200" Height="24" BorderThickness="0" Style="{StaticResource TimeToggle}" />
                    </StackPanel>
                    <Popup IsOpen="{Binding ElementName=btn_ChoseTime, Path=IsChecked}" Placement="Bottom" x:Name="Popup" Focusable="True" AllowsTransparency="True" PopupAnimation="Slide" StaysOpen="False">
                        <Grid Background="#FF122132" >
                            <Grid.RowDefinitions>
                                <RowDefinition Height="24" />
                                <RowDefinition Height="1*" />
                                <RowDefinition Height="30" />
                                <RowDefinition Height="30" />
                            </Grid.RowDefinitions>
                            <Grid Grid.Row="0">
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="1*" />
                                    <ColumnDefinition Width="1*" />
                                </Grid.ColumnDefinitions>
                                <StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center" Grid.Column="0">
                                    <ComboBox x:Name="cmb_Year" Height="22" Width="65"  SelectionChanged="cmb_SelectionChanged" Style="{StaticResource TimeComboBox}"/>
                                    <Label Content="年" Padding="2" HorizontalContentAlignment="Center" VerticalContentAlignment="Center"/>
                                </StackPanel>
                                <StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center" Grid.Column="1" Margin="5,0,0,0">
                                    <ComboBox x:Name="cmb_Mon" Height="22" Width="65"  SelectionChanged="cmb_SelectionChanged" Style="{StaticResource TimeComboBox}"/>
                                    <Label Content="月" Padding="2" HorizontalContentAlignment="Center" VerticalContentAlignment="Center"/>
                                </StackPanel>
                            </Grid>
                            <WrapPanel x:Name="StartWrap" Width="175" Height="100" Grid.Row="1" Margin="12.5,0,12.5,0" />
                            <StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center" Grid.Row="2">
                                <TextBox x:Name="text_Hour" Width="30" HorizontalContentAlignment="Center" PreviewTextInput="TextBox_PreviewTextInput"  VerticalContentAlignment="Center" LostFocus="Text_LostFocus" />
                                <Label Content="时" />
                                <TextBox x:Name="text_Min" Width="30" HorizontalContentAlignment="Center" PreviewTextInput="TextBox_PreviewTextInput"  VerticalContentAlignment="Center"  LostFocus="Text_LostFocus"/>
                                <Label Content="分" />
                                <TextBox x:Name="text_Second" Width="30" HorizontalContentAlignment="Center" PreviewTextInput="TextBox_PreviewTextInput"  VerticalContentAlignment="Center"  LostFocus="Text_LostFocus"/>
                                <Label Content="秒" />
                            </StackPanel>
                            <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Center" Grid.Row="3">
                                <Button x:Name="btn_Clear" Content="重置" Foreground="#FF319FF4" Background="Transparent" BorderThickness="0" Click="btn_Clear_Click"  Width="40"/>
                                <Button x:Name="btn_Sure" Content="确定" Foreground="#FF319FF4" Background="Transparent" BorderThickness="0" Margin="30,0,10,0" Click="btn_Sure_Click"  Width="40"/>
                            </StackPanel>
                        </Grid>
                    </Popup>
                </WrapPanel>
            </Border>
    </Grid>

     

    1.时间展示和开始选择按钮

    大家看到这个布局可能有点疑惑,因为里面有一个ToggleButton的样式,作为我们这个控件展示时间和开始选择的按钮。

    样式如下:

        <Style TargetType="{x:Type ToggleButton}" x:Key="TimeToggle">
            <Setter Property="MinWidth" Value="200" />
            <Setter Property="Height" Value="30" />
            <Setter Property="Background" Value="#FF122132" />
            <Setter Property="Foreground" Value="#96bfd6" />
            <Setter Property="BorderBrush" Value="#FFEAEAEA" />
            <Setter Property="BorderThickness" Value="0" />
            <Setter Property="FontSize"  Value="14" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ToggleButton}">
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="1*" />
                                <ColumnDefinition Width="30" />
                            </Grid.ColumnDefinitions>
                            <ContentPresenter HorizontalAlignment="Center"         VerticalAlignment="Center" Grid.Column="0"/>
                            <Border Background="Transparent" Width="auto" Height="auto" Grid.Column="1">
                                <Border x:Name="Back" Width="19" Height="20" HorizontalAlignment="Center" VerticalAlignment="Center">
                                    <Border.Background>
                                        <ImageBrush ImageSource="/Why_Wpf_UserControls;component/Resource/Images/时间.png"/>
                                    </Border.Background>
                                </Border>
                            </Border>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <Style.Triggers>
                <MultiTrigger>
                    <MultiTrigger.Conditions>
                        <Condition Property="IsMouseOver" Value="true" />
                    </MultiTrigger.Conditions>
                </MultiTrigger>
                <MultiTrigger>
                    <MultiTrigger.Conditions>
                        <Condition Property="IsMouseOver" Value="false" />
                    </MultiTrigger.Conditions>
                </MultiTrigger>
                <Trigger Property="ToggleButton.IsMouseOver" Value="True">
                    <Setter Property="Opacity" Value="0.7" />
                </Trigger>
                <Trigger Property="ToggleButton.IsEnabled" Value="False">
                    <Setter Property="ToggleButton.Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type ToggleButton}">
                                <Border CornerRadius="3" BorderThickness="0" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}">
                                    <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
                                </Border>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Trigger>
            </Style.Triggers>
        </Style>

     

    这里简单的讲解一下。首先,我们的修改ComboBox的样式。

    我们把ComboBox分成两个部分,一个部分用来显示分本,另一个部分用来显示标识时间选择的按钮。这里我使用的图片大家可以自己到网上搜索,放入项目后就可以使用啦。为了图片显示的比较清楚,所以显示图片的Border的长宽设置成了和图片大小一直。

    修改到这一步其实这个下拉框的样式已经和示意图上显示的差不多了,但是程序一运行以来,大家就会发现,不管是鼠标移入下拉框还是其他的事件,我们这个样式还是采用的系统自带的效果,这样会显得我们的控件看起来格格不入,很粗糙。解决这个问题最容易也是最简单的一个办法,就是修改这些事件的触发效果,让这些事件触发时,整个控件的透明度变化一下就可以啦。

    <Trigger Property="ComboBox.IsMouseOver" Value="True">
          <Setter Property="Opacity" Value="0.7" />
    </Trigger>	
    

    这里的IsEnabled的样式效果为不显示图片,仅显示时间。

     

    2.下拉Popup

    Popup主要用来显示编辑时间的区域,在我们不点击空间时不会展开,所以它的IsOpen属性绑定了我们上面的ToggleButton的IsCheck属性,这也是我们显示时间的控件采用ToggleButton而不是其他控件的原因。

    <Popup IsOpen="{Binding ElementName=btn_ChoseTime, Path=IsChecked}" Placement="Bottom" x:Name="Popup" Focusable="True" AllowsTransparency="True" PopupAnimation="Slide" StaysOpen="False">

    Popup的区域我们从上到下分为四大块,第一块用来放置设置年月的两个ComboBox;第二块用来放置设置日的RadioButton们;第三块用来放置设置时分秒的三个TextBox;第四块用来放置重置和确定按钮。

     

     

     

    第一部分-年月选择

    下面是第一块区域的Xaml。

                            <Grid Grid.Row="0">
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="1*" />
                                    <ColumnDefinition Width="1*" />
                                </Grid.ColumnDefinitions>
                                <StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center" Grid.Column="0">
                                    <ComboBox x:Name="cmb_Year" Height="22" Width="65"  SelectionChanged="cmb_SelectionChanged" Style="{StaticResource TimeComboBox}"/>
                                    <Label Content="年" Padding="2" HorizontalContentAlignment="Center" VerticalContentAlignment="Center"/>
                                </StackPanel>
                                <StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center" Grid.Column="1" Margin="5,0,0,0">
                                    <ComboBox x:Name="cmb_Mon" Height="22" Width="65"  SelectionChanged="cmb_SelectionChanged" Style="{StaticResource TimeComboBox}"/>
                                    <Label Content="月" Padding="2" HorizontalContentAlignment="Center" VerticalContentAlignment="Center"/>
                                </StackPanel>
                            </Grid>

    这部分没有什么值得特别注意的地方,唯一的需要注意的是有一个下拉框的样式。

        <Style TargetType="ComboBox" x:Key="TimeComboBox">
            <Setter Property="VerticalContentAlignment" Value="Center" />
            <Setter Property="BorderThickness" Value="0" />
            <Setter Property="BorderBrush" Value="Transparent" />
            <Setter Property="Foreground" Value="#96bfd6" />
            <Setter Property="Background" Value="#FF172E4D" />
            <Setter Property="BorderBrush" Value="#FF172E4D" />
            <Setter Property="ItemContainerStyle">
                <Setter.Value>
                    <Style TargetType="ComboBoxItem">
                        <Setter Property="MinHeight" Value="22"></Setter>
                        <Setter Property="Template">
                            <Setter.Value>
                                <ControlTemplate TargetType="ComboBoxItem">
                                    <Border Name="Back" Background="{TemplateBinding Background}"  BorderThickness="0,0,0,0" BorderBrush="{TemplateBinding BorderBrush}">
                                        <ContentPresenter ContentSource="{Binding Source}"  VerticalAlignment="Center" HorizontalAlignment="Left" Margin="5,0,0,0"></ContentPresenter>
                                    </Border>
                                    <ControlTemplate.Triggers>
                                        <Trigger Property="IsMouseOver" Value="True">
                                            <Setter TargetName="Back" Property="Background" Value="#FF319FF4"></Setter>
                                        </Trigger>
                                        <Trigger Property="IsHighlighted" Value="True">
                                            <Setter TargetName="Back" Property="Background" Value="#FF319FF4"></Setter>
                                        </Trigger>
                                    </ControlTemplate.Triggers>
                                </ControlTemplate>
                            </Setter.Value>
                        </Setter>
                    </Style>
                </Setter.Value>
            </Setter>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="ComboBox">
                        <Grid Background="{TemplateBinding Background}">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="0.7*" />
                            </Grid.ColumnDefinitions>
                            <ToggleButton  Grid.Column="0" Foreground="{TemplateBinding Foreground}" Background="{TemplateBinding Background}"  Content="{TemplateBinding Text}" VerticalContentAlignment="Center" 
    IsChecked="{Binding Path=IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" ClickMode="Press" BorderThickness="0"></ToggleButton>
                            <Popup IsOpen="{TemplateBinding IsDropDownOpen}" Placement="Bottom" x:Name="Popup" Focusable="False" AllowsTransparency="True" PopupAnimation="Slide">
                                <Border CornerRadius="1" MaxHeight="{TemplateBinding MaxDropDownHeight}" MinWidth="80" x:Name="DropDown" SnapsToDevicePixels="True" Background="{TemplateBinding Background}">
                                    <Border.Effect>
                                        <DropShadowEffect Color="Black" BlurRadius="2" ShadowDepth="0" Opacity="0.5" />
                                    </Border.Effect>
                                    <ScrollViewer Margin="4,6,4,6" Style="{DynamicResource ScrollViewerStyle}" MaxHeight="{TemplateBinding MaxDropDownHeight}" SnapsToDevicePixels="True" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" CanContentScroll="True">
                                        <StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Contained" Background="{TemplateBinding Background}" />
                                    </ScrollViewer>
                                </Border>
                            </Popup>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

    众所周知,下拉框有一个显示区域和下拉区域组成,而WPF自带的下拉区域不改样式的话很难调整,所以我们也在这里重写了ComboBox中的Popup。然后,我们又遇到一个问题,在下拉框很长的时候我们需要一个滚动条来显示,老规矩了,WPF自带的滚动条也不容易调整样式,所以我们又重写了滚动条的样式。

        <Style TargetType="ScrollViewer" x:Key="ScrollViewerStyle">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ScrollViewer}">
                        <Grid x:Name="Grid" Background="{TemplateBinding Background}">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="*" />
                                <ColumnDefinition Width="Auto" />
                            </Grid.ColumnDefinitions>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="*" />
                                <RowDefinition Height="Auto" />
                            </Grid.RowDefinitions>
                            <!--右下角四方形-->
                            <Rectangle x:Name="Corner"  Grid.Row="1" Grid.Column="1" Fill="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" />
                            <!--内容区域-->
                            <ScrollContentPresenter x:Name="PART_ScrollContentPresenter" Grid.Row="0" Grid.Column="0" Content="{TemplateBinding Content}" CanContentScroll="{TemplateBinding CanContentScroll}"  ContentTemplate="{TemplateBinding ContentTemplate}" Margin="{TemplateBinding Padding}" />
                            <!--竖直滚动条-->
                            <ScrollBar x:Name="PART_VerticalScrollBar"   Grid.Row="0" Grid.Column="1" AutomationProperties.AutomationId="VerticalScrollBar"   Cursor="Arrow" Maximum="{TemplateBinding ScrollableHeight}" Minimum="0" Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"   Value="{Binding VerticalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}"   ViewportSize="{TemplateBinding ViewportHeight}" Style="{DynamicResource ScrollBarStyle}" Background="#152a45"/>
                            <!--水平滚动条-->
                            <ScrollBar x:Name="PART_HorizontalScrollBar" Grid.Row="1" Grid.Column="0" AutomationProperties.AutomationId="HorizontalScrollBar" Cursor="Arrow" Maximum="{TemplateBinding ScrollableWidth}"  Minimum="0" Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" Value="{Binding HorizontalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" ViewportSize="{TemplateBinding ViewportWidth}"  Style="{DynamicResource ScrollBarStyle}" Background="#152a45" Orientation="Horizontal" />
                        </Grid>
                        <ControlTemplate.Triggers>
                            <Trigger Property="HorizontalScrollBarVisibility" Value="Disabled">
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    
        <Style x:Key="VerticalScrollBarPageButton" TargetType="{x:Type RepeatButton}">
            <Setter Property="OverridesDefaultStyle" Value="true" />
            <Setter Property="Background" Value="Transparent" />
            <Setter Property="Focusable" Value="false" />
            <Setter Property="IsTabStop" Value="false" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type RepeatButton}">
                        <Rectangle Fill="{TemplateBinding Background}" Height="{TemplateBinding Height}" Width="{TemplateBinding Width}" />
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    
        <Style x:Key="HorizontalScrollBarPageButton" TargetType="{x:Type RepeatButton}">
            <Setter Property="OverridesDefaultStyle" Value="true" />
            <Setter Property="Background" Value="Transparent" />
            <Setter Property="Focusable" Value="false" />
            <Setter Property="IsTabStop" Value="false" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type RepeatButton}">
                        <Rectangle Fill="{TemplateBinding Background}" Height="{TemplateBinding Height}" Width="{TemplateBinding Width}" />
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    
        <!--Theum-->
        <Style x:Key="ScrollBarThumb" TargetType="{x:Type Thumb}">
            <Setter Property="OverridesDefaultStyle" Value="true" />
            <Setter Property="IsTabStop" Value="false" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Thumb}">
                        <Border x:Name="border" CornerRadius="3" Background="#FF319FF4" BorderThickness="0">
                        </Border>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter Property="Background" TargetName="border" Value="#888888" />
                            </Trigger>
                            <Trigger Property="IsDragging" Value="True">
                                <Setter Property="Background" TargetName="border" Value="#888888" />
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    
        <!--滚动条样式-->
        <Style x:Key="ScrollBarStyle" TargetType="{x:Type ScrollBar}">
            <Setter Property="Stylus.IsPressAndHoldEnabled" Value="false" />
            <Setter Property="Stylus.IsFlicksEnabled" Value="false" />
            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" />
            <Setter Property="Width" Value="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}" />
            <Setter Property="MinWidth" Value="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ScrollBar}">
                        <Grid x:Name="Bg" Background="{TemplateBinding Background}" SnapsToDevicePixels="true">
                            <Grid.RowDefinitions>
                                <RowDefinition MaxHeight="{DynamicResource {x:Static SystemParameters.VerticalScrollBarButtonHeightKey}}" />
                                <RowDefinition Height="0.00001*" />
                                <RowDefinition MaxHeight="{DynamicResource {x:Static SystemParameters.VerticalScrollBarButtonHeightKey}}" />
                            </Grid.RowDefinitions>
                            <!--上箭头-->
                            <RepeatButton Style="{DynamicResource ArrowDownPathButton}" Command="{x:Static ScrollBar.LineUpCommand}" IsEnabled="{TemplateBinding IsMouseOver}" />
                            <!--滑动条 ? 是不是Slider中的滑动条??? -是 -->
                            <Track x:Name="PART_Track" IsDirectionReversed="true" IsEnabled="{TemplateBinding IsMouseOver}" Grid.Row="1">
                                <!--滑动条上部区域-->
                                <Track.DecreaseRepeatButton>
                                    <RepeatButton Command="{x:Static ScrollBar.PageUpCommand}" Style="{StaticResource VerticalScrollBarPageButton}" />
                                </Track.DecreaseRepeatButton>
                                <!--滑动条部分-->
                                <Track.IncreaseRepeatButton>
                                    <RepeatButton Command="{x:Static ScrollBar.PageDownCommand}" Style="{StaticResource VerticalScrollBarPageButton}" />
                                </Track.IncreaseRepeatButton>
                                <!--滑动条下部区域-->
                                <Track.Thumb>
                                    <Thumb Style="{StaticResource ScrollBarThumb}" Margin="3,0,3,0" />
                                </Track.Thumb>
                            </Track>
                            <!--下箭头-->
                            <RepeatButton Command="{x:Static ScrollBar.LineDownCommand}" IsEnabled="{TemplateBinding IsMouseOver}" Grid.Row="2" Style="{DynamicResource ArrowUpPathButton}" />
                        </Grid>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsEnabled" Value="false">
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <Style.Triggers>
                <!--水平摆放时-->
                <Trigger Property="Orientation" Value="Horizontal">
                    <Setter Property="Width" Value="Auto" />
                    <Setter Property="MinWidth" Value="0" />
                    <Setter Property="Height" Value="{DynamicResource {x:Static SystemParameters.HorizontalScrollBarHeightKey}}" />
                    <Setter Property="MinHeight" Value="{DynamicResource {x:Static SystemParameters.HorizontalScrollBarHeightKey}}" />
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type ScrollBar}">
                                <Grid x:Name="Bg" Background="{TemplateBinding Background}" SnapsToDevicePixels="true">
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition MaxWidth="{DynamicResource {x:Static SystemParameters.HorizontalScrollBarButtonWidthKey}}" />
                                        <ColumnDefinition Width="0.00001*" />
                                        <ColumnDefinition MaxWidth="{DynamicResource {x:Static SystemParameters.HorizontalScrollBarButtonWidthKey}}" />
                                    </Grid.ColumnDefinitions>
                                    <RepeatButton Command="{x:Static ScrollBar.LineLeftCommand}" IsEnabled="{TemplateBinding IsMouseOver}" Style="{DynamicResource ArrowLeftPathButton}" />
                                    <Track x:Name="PART_Track" Grid.Column="1" IsEnabled="{TemplateBinding IsMouseOver}">
                                        <Track.DecreaseRepeatButton>
                                            <RepeatButton Command="{x:Static ScrollBar.PageLeftCommand}" Style="{StaticResource HorizontalScrollBarPageButton}" />
                                        </Track.DecreaseRepeatButton>
                                        <Track.IncreaseRepeatButton>
                                            <RepeatButton Command="{x:Static ScrollBar.PageRightCommand}" Style="{StaticResource HorizontalScrollBarPageButton}" />
                                        </Track.IncreaseRepeatButton>
                                        <Track.Thumb>
                                            <Thumb Style="{StaticResource ScrollBarThumb}" Margin="0,3,0,3" />
                                        </Track.Thumb>
                                    </Track>
                                    <RepeatButton Grid.Column="2" Command="{x:Static ScrollBar.LineRightCommand}" IsEnabled="{TemplateBinding IsMouseOver}" Style="{DynamicResource ArrowRightPathButton}" />
                                </Grid>
                                <ControlTemplate.Triggers>
                                    <Trigger Property="IsEnabled" Value="false">
                                    </Trigger>
                                </ControlTemplate.Triggers>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Trigger>
            </Style.Triggers>
        </Style>
    
        <!--下箭头-->
        <Style x:Key="ArrowDownPathButton" TargetType="RepeatButton">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="RepeatButton">
                        <Grid Background="Transparent">
                            <Path x:Name="PathFill" Fill="#868999" Width="13" Height="8" StrokeThickness="0" Data="M5.0000001,0 L10,10 L-2.0915641E-08,10 z" RenderTransformOrigin="0.500000001045782,0.5" Stretch="Fill">
                                <Path.RenderTransform>
                                    <TransformGroup>
                                        <ScaleTransform />
                                        <SkewTransform />
                                        <RotateTransform Angle="180" />
                                        <TranslateTransform />
                                    </TransformGroup>
                                </Path.RenderTransform>
                            </Path>
                        </Grid>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter Property="Fill" TargetName="PathFill" Value="#1C97EA"></Setter>
                            </Trigger>
                            <Trigger Property="IsPressed" Value="True">
                                <Setter Property="Fill" TargetName="PathFill" Value="#FF4D84AE"></Setter>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    
        <!--上箭头-->
        <Style x:Key="ArrowUpPathButton" TargetType="RepeatButton">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="RepeatButton">
                        <Grid Background="Transparent">
                            <Path x:Name="PathFill" Fill="#868999" Width="13" Height="8" VerticalAlignment="Center" HorizontalAlignment="Center"  StrokeThickness="0" Data="M5.0000001,0 L10,10 L-2.0915641E-08,10 z" RenderTransformOrigin="0.500000001045782,0.5" Stretch="Fill">
                                <Path.RenderTransform>
                                    <TransformGroup>
                                        <ScaleTransform />
                                        <SkewTransform />
                                        <RotateTransform Angle="0" />
                                        <TranslateTransform />
                                    </TransformGroup>
                                </Path.RenderTransform>
                            </Path>
                        </Grid>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter Property="Fill" TargetName="PathFill" Value="#1C97EA"></Setter>
                            </Trigger>
                            <Trigger Property="IsPressed" Value="True">
                                <Setter Property="Fill" TargetName="PathFill" Value="#FF4D84AE"></Setter>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    
        <!--左箭头-->
        <Style x:Key="ArrowLeftPathButton" TargetType="RepeatButton">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="RepeatButton">
                        <Grid Background="Transparent">
                            <Path x:Name="PathFill" Fill="#868999" Width="13" Height="8" StrokeThickness="0" Data="M5.0000001,0 L10,10 L-2.0915641E-08,10 z" RenderTransformOrigin="0.500000001045782,0.5" Stretch="Fill">
                                <Path.RenderTransform>
                                    <TransformGroup>
                                        <ScaleTransform />
                                        <SkewTransform />
                                        <RotateTransform Angle="-90" />
                                        <TranslateTransform />
                                    </TransformGroup>
                                </Path.RenderTransform>
                            </Path>
                        </Grid>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter Property="Fill" TargetName="PathFill" Value="#1C97EA"></Setter>
                            </Trigger>
                            <Trigger Property="IsPressed" Value="True">
                                <Setter Property="Fill" TargetName="PathFill" Value="#FF4D84AE"></Setter>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    
        <!--右箭头-->
        <Style x:Key="ArrowRightPathButton" TargetType="RepeatButton">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="RepeatButton">
                        <Grid Background="Transparent">
                            <Path x:Name="PathFill" Fill="#868999" Width="13" Height="8" VerticalAlignment="Center" HorizontalAlignment="Center"  StrokeThickness="0" Data="M5.0000001,0 L10,10 L-2.0915641E-08,10 z" RenderTransformOrigin="0.500000001045782,0.5" Stretch="Fill">
                                <Path.RenderTransform>
                                    <TransformGroup>
                                        <ScaleTransform />
                                        <SkewTransform />
                                        <RotateTransform Angle="90" />
                                        <TranslateTransform />
                                    </TransformGroup>
                                </Path.RenderTransform>
                            </Path>
                        </Grid>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter Property="Fill" TargetName="PathFill" Value="#1C97EA"></Setter>
                            </Trigger>
                            <Trigger Property="IsPressed" Value="True">
                                <Setter Property="Fill" TargetName="PathFill" Value="#FF4D84AE"></Setter>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

    滑动条的样式非常复杂,这里我找了大佬写的滑动条样式,自己做了一些修改以适合我们的控件。此时,我们的下拉框已经成型了,下面给大家看下效果。

     

     

     

    第二部分-Day的选择

    参考WIN10日历的风格,我们打算把日期的选择做成一群按钮中选中一个的选择方式。这里的逻辑主要都在后台,在控件的Xaml中,我们用一个WrapPanel来放置我们的日期按钮。

                            <WrapPanel x:Name="StartWrap" Width="175" Height="100" Grid.Row="1" Margin="12.5,0,12.5,0" />
    

    当然,日期按钮为了适合我们的控件样式,我们也需要进行样式的修改。为了方便开发,我在这里设置了WrapPanel和日期按钮控件具体的长和宽。

        <Style TargetType="RadioButton" x:Key="DayRadioButton">
            <Setter Property="Width" Value="25" />
            <Setter Property="Height" Value="20" />
            <Setter Property="BorderThickness" Value="0" />
            <Setter Property="Background" Value="Transparent" />
            <Setter Property="Foreground" Value="#96bfd6" />
            <Setter Property="BorderBrush" Value="#FF1CB6E4" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type RadioButton}">
                        <Border  BorderThickness="0" Background="{TemplateBinding Background}"  BorderBrush="{TemplateBinding BorderBrush}">
                            <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <Style.Triggers>
                <Trigger Property="RadioButton.IsChecked" Value="True">
                    <Setter Property="RadioButton.Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type RadioButton}">
                                <Grid>
                                    <Border  BorderThickness="1" Background="{TemplateBinding Background}"  BorderBrush="{TemplateBinding BorderBrush}">
                                        <Border.Triggers>
                                            <EventTrigger RoutedEvent="FrameworkElement.Loaded">
                                                <BeginStoryboard Name="BorderBlink" >
                                                    <Storyboard>
                                                        <DoubleAnimation Storyboard.TargetProperty="(UIElement.Opacity)" From="0.3" To="1" RepeatBehavior="Forever" AutoReverse="True" Duration="0:0:0:0.3"/>
                                                        <ColorAnimation From="#FF1CB6E4" To="GreenYellow" Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)" AutoReverse="False" RepeatBehavior="Forever" Duration="0:0:1"/>
                                                    </Storyboard>
                                                </BeginStoryboard>
                                            </EventTrigger>
                                        </Border.Triggers>
                                    </Border>
                                    <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
                                </Grid>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Trigger>
                <Trigger Property="RadioButton.IsMouseOver" Value="True">
                    <Setter Property="Opacity" Value="0.5" />
                </Trigger>
                <Trigger Property="RadioButton.IsEnabled" Value="False">
                    <Setter Property="Opacity" Value="0.5" />
                </Trigger>
            </Style.Triggers>
        </Style>

    在这个日期按钮的样式中,为了使我们的控件有趣一点,给按钮的选中效果添加了两个动画,一个是按钮的边框闪烁,另外一个是按钮的边框颜色变化。由于第一次写博客也没制作过动图,这里的展示就看不出来动画效果了。

     

     

     

    第三部分-时分秒

    这一部分非常简单,结合我们之前在Grid里写的样式,很容易就能实现示意图上的效果。

                            <StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center" Grid.Row="2">
                                <TextBox x:Name="text_Hour" Width="30" HorizontalContentAlignment="Center" PreviewTextInput="TextBox_PreviewTextInput"  VerticalContentAlignment="Center" LostFocus="Text_LostFocus" />
                                <Label Content="时" />
                                <TextBox x:Name="text_Min" Width="30" HorizontalContentAlignment="Center" PreviewTextInput="TextBox_PreviewTextInput"  VerticalContentAlignment="Center"  LostFocus="Text_LostFocus"/>
                                <Label Content="分" />
                                <TextBox x:Name="text_Second" Width="30" HorizontalContentAlignment="Center" PreviewTextInput="TextBox_PreviewTextInput"  VerticalContentAlignment="Center"  LostFocus="Text_LostFocus"/>
                                <Label Content="秒" />
                            </StackPanel>

    需要注意的是,TextBox中的PreviewTextInput用来限制我们的输入,毕竟分钟不能接收1000这样的数据。

     

     

     

    第四部分-重置与确定

    这一部分也非常简单,直接放置两个按钮,微调一下就可以啦。

                        <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Center" Grid.Row="3">
                                <Button x:Name="btn_Clear" Content="重置" Foreground="#FF319FF4" Background="Transparent" BorderThickness="0" Click="btn_Clear_Click"  Width="40"/>
                                <Button x:Name="btn_Sure" Content="确定" Foreground="#FF319FF4" Background="Transparent" BorderThickness="0" Margin="30,0,10,0" Click="btn_Sure_Click"  Width="40"/>
                            </StackPanel>

     

    到这里,我们前端的工作就做完了,接下来该完善控件的后台逻辑了。

     

     

     

    三、后台逻辑

    为了让我们的控件使用起来更方便,需要设置一个依赖属性。

            #region 依赖属性
            /// <summary>
            /// 时间
            /// </summary>
            public DateTime TimeValue
            {
                get { return (DateTime)GetValue(TimeValueProperty); }
                set { SetValue(TimeValueProperty, value); }
            }
    
            public static readonly DependencyProperty TimeValueProperty =
                DependencyProperty.Register("TimeValue", typeof(DateTime), typeof(TimePick), new PropertyMetadata(DateTime.Now, (sender, e) =>
                {
                    var dp = sender as TimePick;
                    if (dp == null) return;
                    dp.GetTime();
                }));
            #endregion

    这个依赖属性用于我们展示时间的ToggleButton的绑定,由于这是一个DateTime,所以绑定的时候需要一个转换器才能正确运行。

        public class DateToString : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            {
                string timeStr = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                if (value != null)
                {
                    try
                    {
                        DateTime dateTime = (DateTime)value;
    
                        timeStr = dateTime.ToString("yyyy-MM-dd HH:mm:ss");
                    }
                    catch
                    {
                        timeStr = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                    }
                }
                return timeStr;
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
            {
                DateTime dateTime = DateTime.Now;
                if (value != null)
                {
                    try
                    {
                        string timeStr = (string)value;
    
                        dateTime = System.Convert.ToDateTime(timeStr);
                    }
                    catch
                    {
                        dateTime = DateTime.Now;
                    }
                }
                return dateTime;
            }
        }

    由于我们显示的时间绑定了依赖属性TimeValue,所以我们各种操作只需要修改这个TimeValue,界面上的时间就会自动修改了。并且在使用这个TimePick控件时,只要设置了TimePick的TimeValue属性,界面上的值也会跟着刷新。

    ToggleButton上面显示的时间刷新了,接下来该完善Popup中的逻辑。首先,我们的第二块显示日期区域中有多少按钮是由选中的月份决定的,所以我们先完善月份的ComboBox的逻辑。

            private void cmb_SelectionChanged(object sender, SelectionChangedEventArgs e)
            {
                if (cmb_Year.SelectedValue != null && cmb_Mon.SelectedValue != null)
                {
                    days.Clear();
                    StartWrap.Children.Clear();
                    int SelectedMon = (int)cmb_Mon.SelectedValue;
                    switch (SelectedMon)
                    {
                        case 1:
                        case 3:
                        case 5:
                        case 7:
                        case 8:
                        case 10:
                        case 12:
                            for (int i = 1; i < 32; i++)
                            {
                                RadioButton daybutton = new RadioButton();
                                daybutton.Content = i.ToString().PadLeft(2, '0');
                                daybutton.Click += Start_Daybutton_Click;
                                StartWrap.Children.Add(daybutton);
                                days.Add(daybutton);
                            }
                            break;
                        case 2:
                            if (cmb_Year.SelectedValue != null)
                            {
                                int temp = int.Parse(cmb_Year.SelectedValue.ToString());
                                if (temp % 4 == 0)
                                {
                                    if (temp % 100 == 0)
                                    {
                                        if (temp % 400 == 0)
                                        {
                                            for (int i = 1; i < 30; i++)
                                            {
                                                RadioButton daybutton = new RadioButton();
                                                daybutton.Content = i.ToString().PadLeft(2, '0');
                                                daybutton.Click += Start_Daybutton_Click;
                                                StartWrap.Children.Add(daybutton);
                                                days.Add(daybutton);
                                            }
                                        }
                                        else
                                        {
                                            for (int i = 1; i < 29; i++)
                                            {
                                                RadioButton daybutton = new RadioButton();
                                                daybutton.Content = i.ToString().PadLeft(2, '0');
                                                daybutton.Click += Start_Daybutton_Click;
                                                StartWrap.Children.Add(daybutton);
                                                days.Add(daybutton);
                                            }
                                        }
                                    }
                                    else
                                    {
                                        for (int i = 1; i < 30; i++)
                                        {
                                            RadioButton daybutton = new RadioButton();
                                            daybutton.Content = i.ToString().PadLeft(2, '0');
                                            daybutton.Click += Start_Daybutton_Click;
                                            StartWrap.Children.Add(daybutton);
                                            days.Add(daybutton);
                                        }
                                    }
                                }
                                else
                                {
                                    for (int i = 1; i < 29; i++)
                                    {
                                        RadioButton daybutton = new RadioButton();
                                        daybutton.Content = i.ToString().PadLeft(2, '0');
                                        daybutton.Click += Start_Daybutton_Click;
                                        StartWrap.Children.Add(daybutton);
                                        days.Add(daybutton);
                                    }
                                }
                            }
                            break;
                        default:
                            for (int i = 1; i < 31; i++)
                            {
                                RadioButton daybutton = new RadioButton();
                                daybutton.Content = i.ToString().PadLeft(2, '0');
                                daybutton.Click += Start_Daybutton_Click;
                                StartWrap.Children.Add(daybutton);
                                days.Add(daybutton);
                            }
                            break;
                    }
                    TimeValue = new DateTime(int.Parse(cmb_Year.SelectedValue.ToString()), int.Parse(cmb_Mon.SelectedValue.ToString()), TimeValue.Day, TimeValue.Hour, TimeValue.Minute, TimeValue.Second);
                }
            }

    这里写的比较简单,每个月份的天数都不同,闰年的2月和非闰年的2月天数也不同。在选中月份后,根据相应的月份创建对应天数的RadioButton放入WrapPanel中,由于我们的Xaml中已经设置了Radio的默认样式为之前开发的“DayButton”,所以这里不用再设置样式。在月份下拉框选中改变时,记得更新TimeValue属性。年份的下拉框的选中改变事件也可以复用该逻辑,因为内部已经做了区分。

    此时我们的日期按钮也全部添加进界面中了,现在该为它们添加选中事件的逻辑了。

            private void Start_Daybutton_Click(object sender, RoutedEventArgs e)
            {
                RadioButton temp = sender as RadioButton;
                if (temp != null)
                {
                    TimeValue = new DateTime(TimeValue.Year, TimeValue.Month, int.Parse(temp.Content.ToString()), TimeValue.Hour, TimeValue.Minute, TimeValue.Second);
                }
            }

    这里的逻辑很简单,只需要更新一下TimeValue的值就行了。

     

    年月日的逻辑已经编写完了,接下来该编写时分秒的逻辑了,之前我们在Xaml中已经指定了相应的事件,这里完善它们就可以了。

            private void TextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
            {
                Regex re = new Regex("[^0-9]+");
                e.Handled = re.IsMatch(e.Text);
            }

    PreviewTextInput作为TextBox的输入响应事件,和TextInput的区别在于它触发在TextBox的值被设置之前,所以我们可以在这里用正则表达式来限定一下输入。

            private void Text_LostFocus(object sender, RoutedEventArgs e)
            {
                TextBox temp = sender as TextBox;
                if (temp != null)
                {
                    if (string.IsNullOrEmpty(temp.Text))
                    {
                        return;
                    }
                    switch (temp.Name)
                    {
                        case "text_StartHour":
                            if (int.Parse(temp.Text) < 0)
                            {
                                temp.Text = "0";
                            }
                            else if (int.Parse(temp.Text) > 23)
                            {
                                temp.Text = "23";
                            }
                            break;
                        case "text_StartMin":
                            if (int.Parse(temp.Text) < 0)
                            {
                                temp.Text = "0";
                            }
                            else if (int.Parse(temp.Text) > 59)
                            {
                                temp.Text = "59";
                            }
                            break;
                        case "text_StartSecond":
                            if (int.Parse(temp.Text) < 0)
                            {
                                temp.Text = "0";
                            }
                            else if (int.Parse(temp.Text) > 59)
                            {
                                temp.Text = "59";
                            }
                            break;
                        default:
                            break;
                    }
                    TimeValue = new DateTime(TimeValue.Year, TimeValue.Month, TimeValue.Day, int.Parse(text_Hour.Text), int.Parse(text_Min.Text), int.Parse(text_Second.Text));
                    temp.Text = temp.Text.PadLeft(2, '0');
                }
            }

    LostFocus事件中的逻辑主要用来限制输入的数值范围,当然也可以在正则表达式中一起验证,就不需要再写该事件的逻辑了。笔者的正则表达式用的不好,就采用了这种土方法。

     

     

    UI上元素的相应都做完了,我们还需要做一件事,就是TimeValue被外部修改的时候,我们控件里的Popupz中的年月日时分秒的值也要相应更新。这里我们完善TimeValue值改变时会触发的GetTime效果

            private void GetTime()
            {
                if (TimeValue != null)
                {
                    //开始时间
                    cmb_Year.SelectedValue = TimeValue.Year;
                    cmb_Mon.SelectedValue = TimeValue.Month;
                    cmb_SelectionChanged(null, null);
                    RadioButton temp = days.FirstOrDefault(t => t.Content.ToString() == TimeValue.Day.ToString());
                    if (temp != null)
                    {
                        temp.IsChecked = true;
                    }
                    text_Hour.Text = TimeValue.Hour.ToString().PadLeft(2,'0');
                    text_Min.Text = TimeValue.Minute.ToString().PadLeft(2, '0');
                    text_Second.Text = TimeValue.Second.ToString().PadLeft(2, '0');
                }
            }

    当然,重置和确定的逻辑也要完善。

            private void btn_Clear_Click(object sender, RoutedEventArgs e)
            {
                TimeValue = DateTime.Now;
            }
    
            private void btn_Sure_Click(object sender, RoutedEventArgs e)
            {
                btn_ChoseTime.IsChecked = false;
            }

    最后,我们要在控件初始化的时候给年月的下拉框设置数据。这一步建议放置控件的构造函数中。

            private void InitCmb()
            {
                List<int> YearList = new List<int>();
                for (int i = DateTime.Now.Year - 10; i < DateTime.Now.Year + 15; i++)
                {
                    YearList.Add(i);
                }
                cmb_Year.ItemsSource = YearList;
                List<int> MonList = new List<int>();
                for (int i = 1; i < 13; i++)
                {
                    MonList.Add(i);
    
                }
                cmb_Mon.ItemsSource = MonList;
            }

     

     

    大功告成,我们的事件选择器TimePick就做好了!下面放出整体的后台逻辑代码。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text.RegularExpressions;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Input;
    
    namespace Why_Wpf_UserControls
    {
        /// <summary>
        /// TimePick.xaml 的交互逻辑
        /// </summary>
        public partial class TimePick : UserControl
        {
            #region 依赖属性
            /// <summary>
            /// 时间
            /// </summary>
            public DateTime TimeValue
            {
                get { return (DateTime)GetValue(TimeValueProperty); }
                set { SetValue(TimeValueProperty, value); }
            }
    
            public static readonly DependencyProperty TimeValueProperty =
                DependencyProperty.Register("TimeValue", typeof(DateTime), typeof(TimePick), new PropertyMetadata(DateTime.Now, (sender, e) =>
                {
                    var dp = sender as TimePick;
                    if (dp == null) return;
                    dp.GetTime();
                }));
    
            #endregion
    
            List<RadioButton> days = new List<RadioButton>();
    
            private void GetTime()
            {
                if (TimeValue != null)
                {
                    //开始时间
                    cmb_Year.SelectedValue = TimeValue.Year;
                    cmb_Mon.SelectedValue = TimeValue.Month;
                    cmb_SelectionChanged(null, null);
                    RadioButton temp = days.FirstOrDefault(t => t.Content.ToString() == TimeValue.Day.ToString());
                    if (temp != null)
                    {
                        temp.IsChecked = true;
                    }
                    text_Hour.Text = TimeValue.Hour.ToString().PadLeft(2,'0');
                    text_Min.Text = TimeValue.Minute.ToString().PadLeft(2, '0');
                    text_Second.Text = TimeValue.Second.ToString().PadLeft(2, '0');
                }
            }
    
    
            public TimePick()
            {
                InitializeComponent();
                Init();
            }
    
            private void Init()
            {
                InitCmb();
                TimeValue = DateTime.Now;
            }
    
            private void InitCmb()
            {
                List<int> YearList = new List<int>();
                for (int i = DateTime.Now.Year - 10; i < DateTime.Now.Year + 15; i++)
                {
                    YearList.Add(i);
                }
                cmb_Year.ItemsSource = YearList;
                List<int> MonList = new List<int>();
                for (int i = 1; i < 13; i++)
                {
                    MonList.Add(i);
    
                }
                cmb_Mon.ItemsSource = MonList;
            }
    
            private void btn_Clear_Click(object sender, RoutedEventArgs e)
            {
                TimeValue = DateTime.Now;
            }
    
            private void btn_Sure_Click(object sender, RoutedEventArgs e)
            {
                btn_ChoseTime.IsChecked = false;
            }
    
            private void cmb_SelectionChanged(object sender, SelectionChangedEventArgs e)
            {
                if (cmb_Year.SelectedValue != null && cmb_Mon.SelectedValue != null)
                {
                    days.Clear();
                    StartWrap.Children.Clear();
                    int SelectedMon = (int)cmb_Mon.SelectedValue;
                    switch (SelectedMon)
                    {
                        case 1:
                        case 3:
                        case 5:
                        case 7:
                        case 8:
                        case 10:
                        case 12:
                            for (int i = 1; i < 32; i++)
                            {
                                RadioButton daybutton = new RadioButton();
                                daybutton.Content = i.ToString().PadLeft(2, '0');
                                daybutton.Click += Start_Daybutton_Click;
                                StartWrap.Children.Add(daybutton);
                                days.Add(daybutton);
                            }
                            break;
                        case 2:
                            if (cmb_Year.SelectedValue != null)
                            {
                                int temp = int.Parse(cmb_Year.SelectedValue.ToString());
                                if (temp % 4 == 0)
                                {
                                    if (temp % 100 == 0)
                                    {
                                        if (temp % 400 == 0)
                                        {
                                            for (int i = 1; i < 30; i++)
                                            {
                                                RadioButton daybutton = new RadioButton();
                                                daybutton.Content = i.ToString().PadLeft(2, '0');
                                                daybutton.Click += Start_Daybutton_Click;
                                                StartWrap.Children.Add(daybutton);
                                                days.Add(daybutton);
                                            }
                                        }
                                        else
                                        {
                                            for (int i = 1; i < 29; i++)
                                            {
                                                RadioButton daybutton = new RadioButton();
                                                daybutton.Content = i.ToString().PadLeft(2, '0');
                                                daybutton.Click += Start_Daybutton_Click;
                                                StartWrap.Children.Add(daybutton);
                                                days.Add(daybutton);
                                            }
                                        }
                                    }
                                    else
                                    {
                                        for (int i = 1; i < 30; i++)
                                        {
                                            RadioButton daybutton = new RadioButton();
                                            daybutton.Content = i.ToString().PadLeft(2, '0');
                                            daybutton.Click += Start_Daybutton_Click;
                                            StartWrap.Children.Add(daybutton);
                                            days.Add(daybutton);
                                        }
                                    }
                                }
                                else
                                {
                                    for (int i = 1; i < 29; i++)
                                    {
                                        RadioButton daybutton = new RadioButton();
                                        daybutton.Content = i.ToString().PadLeft(2, '0');
                                        daybutton.Click += Start_Daybutton_Click;
                                        StartWrap.Children.Add(daybutton);
                                        days.Add(daybutton);
                                    }
                                }
                            }
                            break;
                        default:
                            for (int i = 1; i < 31; i++)
                            {
                                RadioButton daybutton = new RadioButton();
                                daybutton.Content = i.ToString().PadLeft(2, '0');
                                daybutton.Click += Start_Daybutton_Click;
                                StartWrap.Children.Add(daybutton);
                                days.Add(daybutton);
                            }
                            break;
                    }
                    TimeValue = new DateTime(int.Parse(cmb_Year.SelectedValue.ToString()), int.Parse(cmb_Mon.SelectedValue.ToString()), TimeValue.Day, TimeValue.Hour, TimeValue.Minute, TimeValue.Second);
                }
            }
    
            private void Start_Daybutton_Click(object sender, RoutedEventArgs e)
            {
                RadioButton temp = sender as RadioButton;
                if (temp != null)
                {
                    TimeValue = new DateTime(TimeValue.Year, TimeValue.Month, int.Parse(temp.Content.ToString()), TimeValue.Hour, TimeValue.Minute, TimeValue.Second);
                }
            }
    
            private void TextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
            {
                Regex re = new Regex("[^0-9]+");
                e.Handled = re.IsMatch(e.Text);
            }
    
            private void Text_LostFocus(object sender, RoutedEventArgs e)
            {
                TextBox temp = sender as TextBox;
                if (temp != null)
                {
                    if (string.IsNullOrEmpty(temp.Text))
                    {
                        return;
                    }
                    switch (temp.Name)
                    {
                        case "text_StartHour":
                            if (int.Parse(temp.Text) < 0)
                            {
                                temp.Text = "0";
                            }
                            else if (int.Parse(temp.Text) > 23)
                            {
                                temp.Text = "23";
                            }
                            break;
                        case "text_StartMin":
                            if (int.Parse(temp.Text) < 0)
                            {
                                temp.Text = "0";
                            }
                            else if (int.Parse(temp.Text) > 59)
                            {
                                temp.Text = "59";
                            }
                            break;
                        case "text_StartSecond":
                            if (int.Parse(temp.Text) < 0)
                            {
                                temp.Text = "0";
                            }
                            else if (int.Parse(temp.Text) > 59)
                            {
                                temp.Text = "59";
                            }
                            break;
                        default:
                            break;
                    }
                    TimeValue = new DateTime(TimeValue.Year, TimeValue.Month, TimeValue.Day, int.Parse(text_Hour.Text), int.Parse(text_Min.Text), int.Parse(text_Second.Text));
                    temp.Text = temp.Text.PadLeft(2, '0');
                }
            }
        }
    }
    

     

     


    总结

    其实我并不想写这么多后台逻辑的,想全部用数据绑定来完成,可惜DateTime的Year,Month,Day等属性全是只读,没法做双向绑定,我非要用绑定的话得再写一个Model来和DateTime交互,觉得太麻烦就没这样做,各位大佬如果有好的方法欢迎指导。

    展开全文
  • WPF自定义时间控件

    2021-05-07 18:09:52
    一:xaml上控件的实现 <!-- 按钮 网格 --> <Grid Grid.Row="0" Grid.Column="3" RenderTransformOrigin="0.492,0.54"> <Grid.ColumnDefinitions> <ColumnDefinition Width="0.13*" />
  • wpf控件style

    2017-08-22 10:35:00
    前段时间一直在做wpf的UI开发,每次想做些控件style定制的时候都很头疼 很多控件不知道他的controltemplate是什么样的 为了方便大家写style 特别奉上wpf的style大全 从此,妈妈再也不用担心我的wpf,哪里不会点...
  • WPF AutoComplete 控件

    千次阅读 2013-11-29 20:12:51
    最近在用WPF开发系统时,需要用到一个输入文本可以显示一个下拉框,显示匹配文本的集合列表。一开始自己做了一个,用用户控件来实现,主要是用一个文本框,一个Pop控件,和一个ListBox控件。功能实现了,但是由于...
  • WPF日期时间控件-DateTimePicker

    热门讨论 2017-08-04 14:41:46
    1.日期时间控件,可以直接点击使用 2.是源代码文件 3.压缩包里面有使用说明文档,并有当初设计时详细的思路流程可以参考
  • WPF原生控件样式重构

    2019-06-17 21:30:45
    WPF中常用控件都有一个默认的自定义样式,当我们想要这个控件的样式变成自己喜欢的样式的时候,要怎么做呢,在VisualStudio中不能直接查看控件样式的,但是在BlendforVisualStudio中可以通过模板来查看 打开Blendfor...
  • 该日历控件WPF控件,样式为个人业余时间制作,希望能给广大的初学者一些设计上和学习上的帮助,源码并不仅仅是日历控件样式
  • wpf RepeatButton控件

    2013-04-26 16:53:47
    重复控件: 两个属性: Delay:从用户按下鼠标左键到开始重复发送click事件的延迟时间.单位为毫秒 Delay数值必须大于等于0 Interval:当用户按下鼠标左键时,每次发出Click事件的时间间隔.单位为毫秒 Interval数值必须...
  • WPF控件

    2020-12-11 19:29:20
    WPF控件 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 开发工具与关键技术:Visual Studio 2015 作者: 李杨 撰写时间:2020-12-10 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~...
  • WPF控件和布局

    2019-05-16 20:28:31
    撰写时间:2019年05月15日 首先一开始我们先说下控件的分类,控件它虽然没有数据这些信息重要,但是控件它也是不可缺失的,毕竟控件还是要控制数据这些的呀,比如查看,删除啊这些,要是仔细观察它,控件是分为6类...
  • 3rd.WPF_控件fromGitHub

    2019-09-26 05:15:25
    1、这是 在找 WPF的 日期时间控件 时找到的:  1.1、c# - DateTimePicker for WPF 4.0 - Stack Overflow.html(https://stackoverflow.com/questions/10658472/datetimepicker-for-wpf-4-0/10658747) ZC:这是...
  • WPF 分页控件

    2011-12-14 15:40:00
    做项目时需要数据分页在网站找了半天也没有找到合适的,没办法自己写个,项目比较着急先凑合写个吧,有时间在重写下。 页面部分代码 <UserControl x:Class="Test.Pager" xmlns=...
  • Visifire WPF 图表控件 破解

    千次阅读 2014-11-05 17:49:45
    可能用WPF生成过图表的开发人员都知道,WPF虽然本身... Visifire 是专为WPF、SliverLight、WP开发人员制定的一套图表控件,实现了一系列的专业图表(如:柱图、点图、雷达、饼图、K线图、以及其组合图等)。 它在4.

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 704
精华内容 281
关键字:

wpf时间控件