WPF类似DatePicker的只可以选择年月的年月选择控件

2 篇文章 0 订阅

最近项目开发中,发现需要一个选择年月而不需要选择日的控件,于是想到基于ComboBox,并模仿DatePicker样子来实现该效果,废话不多说直接上代码:

xaml:

 <Style TargetType="{x:Type ComboBox}">
            <Setter Property="Height" Value="25" />
            <Setter Property="BorderBrush" Value="{StaticResource Border.Static}" />
            <Setter Property="Margin" Value="3" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ComboBox}">
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="0.7*" />
                                <ColumnDefinition Width="0.3*" MaxWidth="30" />
                            </Grid.ColumnDefinitions>
                            <Border
                                Name="border"
                                Grid.Column="0"
                                Grid.ColumnSpan="2"
                                BorderBrush="{TemplateBinding BorderBrush}"
                                BorderThickness="1"
                                CornerRadius="1" />
                            <TextBlock
                                Name="contentHost"
                                Margin="5"
                                Text="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=DateText}" />
                            <TextBlock
                                x:Name="Message"
                                Margin="5"
                                HorizontalAlignment="Left"
                                VerticalAlignment="Center"
                                Foreground="#FF707070"
                                IsHitTestVisible="False"
                                Text="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Watermark}"
                                TextAlignment="Center"
                                Visibility="Collapsed" />

                            <!--  ToggleButton 已数据绑定到 ComboBox 本身以切换 IsDropDownOpen  -->
                            <ToggleButton
                                x:Name="ToggleButton"
                                Grid.Column="0"
                                Grid.ColumnSpan="2"
                                Margin="1"
                                ClickMode="Press"
                                Focusable="false"
                                IsChecked="{Binding Path=IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
                                Style="{StaticResource ArrowToggleButton}" />
                            <!--  Popup 可显示 ComboBox 中的项列表。IsOpen 已数据绑定到通过 ComboBoxToggleButton 来切换的 IsDropDownOpen  -->
                            <Popup
                                x:Name="Popup"
                                Width="160"
                                AllowsTransparency="True"
                                Focusable="False"
                                IsOpen="{TemplateBinding IsDropDownOpen}"
                                Placement="Bottom"
                                PlacementTarget="{Binding ElementName=border}"
                                PopupAnimation="Slide">
                                <Border
                                    x:Name="DropDownBorder"
                                    Background="White"
                                    BorderBrush="#FF3D9CAE"
                                    BorderThickness="1"
                                    CornerRadius="3">
                                    <Grid
                                        x:Name="DropDown"
                                        Width="160"
                                        Height="130"
                                        SnapsToDevicePixels="True">
                                        <Grid.RowDefinitions>
                                            <RowDefinition Height="30" />
                                            <RowDefinition Height="*" />
                                        </Grid.RowDefinitions>
                                        <Border BorderBrush="#FF3D9CAE" BorderThickness="0">
                                            <Grid>
                                                <Grid.ColumnDefinitions>
                                                    <ColumnDefinition Width="30" />
                                                    <ColumnDefinition Width="*" />
                                                    <ColumnDefinition Width="30" />
                                                </Grid.ColumnDefinitions>
                                                <DockPanel Grid.Column="0">
                                                    <Button
                                                        Name="lessBtn"
                                                        Width="30"
                                                        Height="30"
                                                        Click="LessBtn_Click">
                                                        <Button.Style>
                                                            <Style TargetType="{x:Type Button}">
                                                                <Setter Property="BorderBrush" Value="Transparent" />
                                                                <Setter Property="BorderThickness" Value="0" />
                                                                <Setter Property="Background" Value="Transparent" />
                                                                <Setter Property="HorizontalContentAlignment" Value="Center" />
                                                                <Setter Property="Height" Value="Auto" />
                                                                <Setter Property="Width" Value="Auto" />
                                                                <Setter Property="Content" Value="{x:Null}" />
                                                                <Setter Property="Cursor" Value="Hand" />
                                                                <Setter Property="Template">
                                                                    <Setter.Value>
                                                                        <ControlTemplate TargetType="{x:Type Button}">
                                                                            <Grid>
                                                                                <Border
                                                                                    Width="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Width}"
                                                                                    Height="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Height}"
                                                                                    Background="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Background}" />
                                                                                <Path
                                                                                    Name="path"
                                                                                    Width="12"
                                                                                    Height="12"
                                                                                    Fill="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"
                                                                                    Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"
                                                                                    StrokeThickness="2">
                                                                                    <Path.Data>
                                                                                        M6,6  L12,0 L12,12 Z
                                                                                    </Path.Data>
                                                                                </Path>
                                                                            </Grid>
                                                                            <ControlTemplate.Triggers>
                                                                                <Trigger Property="IsMouseOver" Value="True">
                                                                                    <Setter TargetName="path" Property="Stroke" Value="#FF3D9CAE" />
                                                                                    <Setter TargetName="path" Property="Fill" Value="#FF3D9CAE" />
                                                                                </Trigger>
                                                                            </ControlTemplate.Triggers>
                                                                        </ControlTemplate>
                                                                    </Setter.Value>
                                                                </Setter>
                                                            </Style>
                                                        </Button.Style>
                                                    </Button>
                                                </DockPanel>
                                                <Grid Grid.Column="1">
                                                    <StackPanel
                                                        HorizontalAlignment="Center"
                                                        VerticalAlignment="Center"
                                                        Orientation="Horizontal">
                                                        <Label x:Name="year" Content="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Year}" />
                                                        <Label Content="年" />
                                                    </StackPanel>
                                                </Grid>
                                                <DockPanel Grid.Column="2">
                                                    <Button
                                                        Name="addBtn"
                                                        Width="30"
                                                        Height="30"
                                                        Click="AddBtn_Click">
                                                        <Button.Style>
                                                            <Style TargetType="{x:Type Button}">
                                                                <Setter Property="BorderBrush" Value="Transparent" />
                                                                <Setter Property="BorderThickness" Value="0" />
                                                                <Setter Property="Background" Value="Transparent" />
                                                                <Setter Property="HorizontalContentAlignment" Value="Center" />
                                                                <Setter Property="Height" Value="Auto" />
                                                                <Setter Property="Width" Value="Auto" />
                                                                <Setter Property="Content" Value="{x:Null}" />
                                                                <Setter Property="Cursor" Value="Hand" />
                                                                <Setter Property="Template">
                                                                    <Setter.Value>
                                                                        <ControlTemplate TargetType="{x:Type Button}">
                                                                            <Grid>
                                                                                <Border
                                                                                    Width="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Width}"
                                                                                    Height="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Height}"
                                                                                    Background="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Background}" />
                                                                                <Path
                                                                                    Name="path"
                                                                                    Width="12"
                                                                                    Height="12"
                                                                                    Fill="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"
                                                                                    Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"
                                                                                    StrokeThickness="2">
                                                                                    <Path.Data>
                                                                                        M0,0  L0,12 L6,6 Z
                                                                                    </Path.Data>
                                                                                </Path>
                                                                            </Grid>
                                                                            <ControlTemplate.Triggers>
                                                                                <Trigger Property="IsMouseOver" Value="True">
                                                                                    <Setter TargetName="path" Property="Stroke" Value="#FF3D9CAE" />
                                                                                    <Setter TargetName="path" Property="Fill" Value="#FF3D9CAE" />
                                                                                </Trigger>
                                                                            </ControlTemplate.Triggers>
                                                                        </ControlTemplate>
                                                                    </Setter.Value>
                                                                </Setter>
                                                            </Style>
                                                        </Button.Style>
                                                    </Button>
                                                </DockPanel>
                                            </Grid>

                                        </Border>
                                        <Grid Grid.Row="1" Margin="3">
                                            <WrapPanel
                                                Name="buttonsHost"
                                                HorizontalAlignment="Center"
                                                VerticalAlignment="Center">
                                                <ToggleButton
                                                    Width="30"
                                                    Height="20"
                                                    Click="ToggleButton_Click"
                                                    Content="1月"
                                                    Style="{StaticResource ToggleButtonStyle.AnnualCalendar.Month}"
                                                    Tag="1">
                                                    <ToggleButton.IsChecked>
                                                        <MultiBinding Converter="{StaticResource monthCheckOrNoConverter}" Mode="OneWay">
                                                            <Binding Path="NowMonth" RelativeSource="{RelativeSource Mode=TemplatedParent}" />
                                                            <Binding Path="Tag" RelativeSource="{RelativeSource Mode=Self}" />
                                                        </MultiBinding>
                                                    </ToggleButton.IsChecked>
                                                </ToggleButton>
                                                <ToggleButton
                                                    Width="30"
                                                    Height="20"
                                                    Click="ToggleButton_Click"
                                                    Content="2月"
                                                    Style="{StaticResource ToggleButtonStyle.AnnualCalendar.Month}"
                                                    Tag="2">
                                                    <ToggleButton.IsChecked>
                                                        <MultiBinding Converter="{StaticResource monthCheckOrNoConverter}" Mode="OneWay">
                                                            <Binding Path="NowMonth" RelativeSource="{RelativeSource Mode=TemplatedParent}" />
                                                            <Binding Path="Tag" RelativeSource="{RelativeSource Mode=Self}" />
                                                        </MultiBinding>
                                                    </ToggleButton.IsChecked>
                                                </ToggleButton>
                                                <ToggleButton
                                                    Width="30"
                                                    Height="20"
                                                    Click="ToggleButton_Click"
                                                    Content="3月"
                                                    Style="{StaticResource ToggleButtonStyle.AnnualCalendar.Month}"
                                                    Tag="3">
                                                    <ToggleButton.IsChecked>
                                                        <MultiBinding Converter="{StaticResource monthCheckOrNoConverter}" Mode="OneWay">
                                                            <Binding Path="NowMonth" RelativeSource="{RelativeSource Mode=TemplatedParent}" />
                                                            <Binding Path="Tag" RelativeSource="{RelativeSource Mode=Self}" />
                                                        </MultiBinding>
                                                    </ToggleButton.IsChecked>
                                                </ToggleButton>
                                                <ToggleButton
                                                    Width="30"
                                                    Height="20"
                                                    Click="ToggleButton_Click"
                                                    Content="4月"
                                                    Style="{StaticResource ToggleButtonStyle.AnnualCalendar.Month}"
                                                    Tag="4">
                                                    <ToggleButton.IsChecked>
                                                        <MultiBinding Converter="{StaticResource monthCheckOrNoConverter}" Mode="OneWay">
                                                            <Binding Path="NowMonth" RelativeSource="{RelativeSource Mode=TemplatedParent}" />
                                                            <Binding Path="Tag" RelativeSource="{RelativeSource Mode=Self}" />
                                                        </MultiBinding>
                                                    </ToggleButton.IsChecked>
                                                </ToggleButton>
                                                <ToggleButton
                                                    Width="30"
                                                    Height="20"
                                                    Click="ToggleButton_Click"
                                                    Content="5月"
                                                    Style="{StaticResource ToggleButtonStyle.AnnualCalendar.Month}"
                                                    Tag="5">
                                                    <ToggleButton.IsChecked>
                                                        <MultiBinding Converter="{StaticResource monthCheckOrNoConverter}" Mode="OneWay">
                                                            <Binding Path="NowMonth" RelativeSource="{RelativeSource Mode=TemplatedParent}" />
                                                            <Binding Path="Tag" RelativeSource="{RelativeSource Mode=Self}" />
                                                        </MultiBinding>
                                                    </ToggleButton.IsChecked>
                                                </ToggleButton>
                                                <ToggleButton
                                                    Width="30"
                                                    Height="20"
                                                    Click="ToggleButton_Click"
                                                    Content="6月"
                                                    Style="{StaticResource ToggleButtonStyle.AnnualCalendar.Month}"
                                                    Tag="6">
                                                    <ToggleButton.IsChecked>
                                                        <MultiBinding Converter="{StaticResource monthCheckOrNoConverter}" Mode="OneWay">
                                                            <Binding Path="NowMonth" RelativeSource="{RelativeSource Mode=TemplatedParent}" />
                                                            <Binding Path="Tag" RelativeSource="{RelativeSource Mode=Self}" />
                                                        </MultiBinding>
                                                    </ToggleButton.IsChecked>
                                                </ToggleButton>
                                                <ToggleButton
                                                    Width="30"
                                                    Height="20"
                                                    Click="ToggleButton_Click"
                                                    Content="7月"
                                                    Style="{StaticResource ToggleButtonStyle.AnnualCalendar.Month}"
                                                    Tag="7">
                                                    <ToggleButton.IsChecked>
                                                        <MultiBinding Converter="{StaticResource monthCheckOrNoConverter}" Mode="OneWay">
                                                            <Binding Path="NowMonth" RelativeSource="{RelativeSource Mode=TemplatedParent}" />
                                                            <Binding Path="Tag" RelativeSource="{RelativeSource Mode=Self}" />
                                                        </MultiBinding>
                                                    </ToggleButton.IsChecked>
                                                </ToggleButton>
                                                <ToggleButton
                                                    Width="30"
                                                    Height="20"
                                                    Click="ToggleButton_Click"
                                                    Content="8月"
                                                    Style="{StaticResource ToggleButtonStyle.AnnualCalendar.Month}"
                                                    Tag="8">
                                                    <ToggleButton.IsChecked>
                                                        <MultiBinding Converter="{StaticResource monthCheckOrNoConverter}" Mode="OneWay">
                                                            <Binding Path="NowMonth" RelativeSource="{RelativeSource Mode=TemplatedParent}" />
                                                            <Binding Path="Tag" RelativeSource="{RelativeSource Mode=Self}" />
                                                        </MultiBinding>
                                                    </ToggleButton.IsChecked>
                                                </ToggleButton>
                                                <ToggleButton
                                                    Width="30"
                                                    Height="20"
                                                    Click="ToggleButton_Click"
                                                    Content="9月"
                                                    Style="{StaticResource ToggleButtonStyle.AnnualCalendar.Month}"
                                                    Tag="9">
                                                    <ToggleButton.IsChecked>
                                                        <MultiBinding Converter="{StaticResource monthCheckOrNoConverter}" Mode="OneWay">
                                                            <Binding Path="NowMonth" RelativeSource="{RelativeSource Mode=TemplatedParent}" />
                                                            <Binding Path="Tag" RelativeSource="{RelativeSource Mode=Self}" />
                                                        </MultiBinding>
                                                    </ToggleButton.IsChecked>
                                                </ToggleButton>
                                                <ToggleButton
                                                    Width="30"
                                                    Height="20"
                                                    Click="ToggleButton_Click"
                                                    Content="10月"
                                                    Style="{StaticResource ToggleButtonStyle.AnnualCalendar.Month}"
                                                    Tag="10">
                                                    <ToggleButton.IsChecked>
                                                        <MultiBinding Converter="{StaticResource monthCheckOrNoConverter}" Mode="OneWay">
                                                            <Binding Path="NowMonth" RelativeSource="{RelativeSource Mode=TemplatedParent}" />
                                                            <Binding Path="Tag" RelativeSource="{RelativeSource Mode=Self}" />
                                                        </MultiBinding>
                                                    </ToggleButton.IsChecked>
                                                </ToggleButton>
                                                <ToggleButton
                                                    Width="30"
                                                    Height="20"
                                                    Click="ToggleButton_Click"
                                                    Content="11月"
                                                    Style="{StaticResource ToggleButtonStyle.AnnualCalendar.Month}"
                                                    Tag="11">
                                                    <ToggleButton.IsChecked>
                                                        <MultiBinding Converter="{StaticResource monthCheckOrNoConverter}" Mode="OneWay">
                                                            <Binding Path="NowMonth" RelativeSource="{RelativeSource Mode=TemplatedParent}" />
                                                            <Binding Path="Tag" RelativeSource="{RelativeSource Mode=Self}" />
                                                        </MultiBinding>
                                                    </ToggleButton.IsChecked>
                                                </ToggleButton>
                                                <ToggleButton
                                                    Width="30"
                                                    Height="20"
                                                    Click="ToggleButton_Click"
                                                    Content="12月"
                                                    Style="{StaticResource ToggleButtonStyle.AnnualCalendar.Month}"
                                                    Tag="12">
                                                    <ToggleButton.IsChecked>
                                                        <MultiBinding Converter="{StaticResource monthCheckOrNoConverter}" Mode="OneWay">
                                                            <Binding Path="NowMonth" RelativeSource="{RelativeSource Mode=TemplatedParent}" />
                                                            <Binding Path="Tag" RelativeSource="{RelativeSource Mode=Self}" />
                                                        </MultiBinding>
                                                    </ToggleButton.IsChecked>
                                                </ToggleButton>
                                            </WrapPanel>
                                        </Grid>
                                    </Grid>
                                </Border>
                            </Popup>
                        </Grid>
                        <ControlTemplate.Triggers>
                            <!--  1.显示水印  -->
                            <DataTrigger Binding="{Binding ElementName=contentHost, Path=Text}" Value="">
                                <Setter TargetName="Message" Property="Visibility" Value="Visible" />
                            </DataTrigger>
                            <Trigger Property="IsMouseOver" Value="true">
                                <Setter TargetName="border" Property="BorderBrush" Value="{StaticResource Border.MouseOver}" />
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

 

xaml.cs:

public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            if (NowYear == 0) { Year = DateTime.Now.Year; } else { Year = NowYear; }
            if (NowYear != 0 && NowMonth != 0) { DateText = ToDateText(NowYear, NowMonth); }
        }


        #region dependency proeprties
        public static readonly DependencyProperty NowMonthProperty = DependencyProperty.Register(
           "NowMonth",
           typeof(int),
           typeof(AnnualCalendarTest),
           new FrameworkPropertyMetadata(0)
           );


        public int NowMonth
        {
            get { return (int)GetValue(NowMonthProperty); }
            set { SetValue(NowMonthProperty, value); }
        }

        public static readonly DependencyProperty NowYearProperty = DependencyProperty.Register(
           "NowYear",
           typeof(int),
           typeof(AnnualCalendarTest),
           new FrameworkPropertyMetadata(0)
           );

        public int NowYear
        {
            get { return (int)GetValue(NowYearProperty); }
            set { SetValue(NowYearProperty, value); }
        }

        public static readonly DependencyProperty DateTextProperty = DependencyProperty.Register(
            "DateText",
            typeof(string),
            typeof(AnnualCalendarTest),
            new PropertyMetadata(null)
            );

        private static void DateTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Console.WriteLine("date text changed");
        }

        public string DateText
        {
            get { return (string)GetValue(DateTextProperty); }
            set { SetValue(DateTextProperty, value); }
        }


        public static readonly DependencyProperty YearProperty = DependencyProperty.Register(
            "Year",
            typeof(int),
            typeof(AnnualCalendarTest)
            );

        public int Year
        {
            get { return (int)GetValue(YearProperty); }
            set { SetValue(YearProperty, value); }
        }

        #region WatermarkProperty 水印
        /// <summary>
        /// 水印
        /// </summary>
        public static readonly DependencyProperty WatermarkProperty = DependencyProperty.RegisterAttached(
            "Watermark", typeof(string), typeof(AnnualCalendarTest), new FrameworkPropertyMetadata(""));

        public static string GetWatermark(DependencyObject d)
        {
            return (string)d.GetValue(WatermarkProperty);
        }

        public static void SetWatermark(DependencyObject obj, string value)
        {
            obj.SetValue(WatermarkProperty, value);
        }
        #endregion
        #endregion

        private ToggleButton[] GetToggleButtons(DependencyObject visual)
        {
            if (visual is ToggleButton toggleButton)
            {
                // assume the toggle button not contains any toggle button
                return new ToggleButton[] { toggleButton };
            }

            List<ToggleButton> toggleButtons = new List<ToggleButton>();
            int childCount = VisualTreeHelper.GetChildrenCount(visual);
            for (int i = 0; i < childCount; i++)
            {
                DependencyObject child = VisualTreeHelper.GetChild(visual, i);
                if (child == null) { continue; }

                ToggleButton[] childToggleButtons = GetToggleButtons(child);
                toggleButtons.AddRange(childToggleButtons);

            }

            return toggleButtons.ToArray();
        }

        private int _month = 1;
        private void ToggleButton_Click(object sender, RoutedEventArgs e)
        {
            ToggleButton tg = (ToggleButton)sender;

            ToggleButton[] buttons = GetToggleButtons(tg.Parent);
            foreach (var button in buttons)
            {
                if (object.ReferenceEquals(button, tg))
                {
                    button.IsChecked = true;
                }
                else
                {
                    button.IsChecked = false;
                }
            }

            _month = int.Parse(tg.Tag.ToString());

            DateText = ToDateText(Year, _month);
            IsDropDownOpen = false;
        }

        /// <summary>
        /// add year
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void AddBtn_Click(object sender, RoutedEventArgs e)
        {
            Year += 1;
            DateText = ToDateText(Year, _month);
        }
        /// <summary>
        /// less year
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void LessBtn_Click(object sender, RoutedEventArgs e)
        {
            Year -= 1;
            DateText = ToDateText(Year, _month);
        }

        private string ToDateText(int year, int month)
        {
            string monthText = month < 10 ? $"0{month}" : month.ToString();
            return $"{year}.{monthText}";
        }

 

实现效果如下:

最后附上源码链接https://download.csdn.net/download/weixin_39552347/12657757

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值