You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF DatePicker模板自定义后SelectedDate绑定失效求助

问题:WPF DatePicker模板重写后SelectedDate绑定失效

最初尝试通过自定义控件实现DatePicker的定制设计,耗时2天还出现SelectedDateChanged事件多次触发的问题,于是改用重写模板的方案,但现在遇到SelectedDate绑定失效的问题:日历中能看到日期变化,事件也会触发,SelectedDate本身有变更,但绑定到ViewModel的属性不生效。

DatePicker模板

<Style x:Key="DatePickerStyle" TargetType="{x:Type DatePicker}">
    <Style.Resources>
        <conv:MonthToGenitiveMonthNameConverter x:Key="MonthToGenitiveMonthNameConverter"/>
        <conv:MonthToAbbreviatedMonthNameConverter x:Key="MonthToAbbreviatedMonthNameConverter"/>
        <conv:DayToDayNameConverter x:Key="DayToDayNameConverter"/>
        <conv:DateToTwoDigitDateConverter x:Key="DateToTwoDigitDateConverter"/>
    </Style.Resources>
    <Setter Property="Foreground" Value="White"/>
    <Setter Property="Height" Value="70"/>
    <Setter Property="Width" Value="500"/>
    <Setter Property="IsTodayHighlighted" Value="True"/>
    <Setter Property="SelectedDateFormat" Value="Short"/>
    <Setter Property="Background" Value="Transparent"/>
    <Setter Property="Padding" Value="2"/>
    <Setter Property="BorderBrush" Value="Transparent"/>
    <Setter Property="BorderThickness" Value="1"/>
    <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type DatePicker}">
                <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}">
                    <Grid x:Name="PART_Root" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
                        <Grid  HorizontalAlignment="Stretch">
                            <StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
                                <TextBlock Margin="5 0 0 0" Foreground="{TemplateBinding Foreground}" FontSize="50" Text="{Binding Path=SelectedDate.Day, Converter={StaticResource DateToTwoDigitDateConverter}}" />
                                <StackPanel Margin="10,2,0,2" VerticalAlignment="Center" >
                                    <TextBlock Foreground="{TemplateBinding Foreground}" FontSize="24" FontWeight="Bold" Text="{Binding Path=SelectedDate.Month, Converter={StaticResource MonthToGenitiveMonthNameConverter}}"/>
                                    <TextBlock Foreground="{TemplateBinding Foreground}" FontSize="14" Text="{Binding Path=SelectedDate.DayOfWeek, Converter={StaticResource DayToDayNameConverter}}"/>
                                </StackPanel>
                                <TextBlock Margin="5 0 0 0" Foreground="{TemplateBinding Foreground}" FontSize="50" Text="{Binding Path=SelectedDate.Year}" />
                                <TextBlock Margin="5 0 0 0" Foreground="{TemplateBinding Foreground}" FontSize="50" Text="г." />
                            </StackPanel>
                            <StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
                                <Button Name="PART_Button" Style="{StaticResource ExtendedDataPickerButtonStyle}">
                                    <fa:IconImage Icon="Calendar"  Style="{StaticResource BigIconStyle}"/>
                                </Button>
                                <DatePickerTextBox x:Name="PART_TextBox" Visibility="Collapsed"/>
                                <Popup x:Name="PART_Popup" AllowsTransparency="True" Placement="Bottom" PlacementTarget="{Binding ElementName=PART_Button}" StaysOpen="False" 
                                       ui:PopupProperties.HorizontalPlacementAlignment="Center"
                                       ui:PopupProperties.VerticalOffset="2"/>
                            </StackPanel>
                        </Grid>
                    </Grid>
                </Border>
               
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

转换器代码

DateToTwoDigitDateConverter

[ValueConversion(typeof(string), typeof(int))]
class DateToTwoDigitDateConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        int val = (int)value;
        if (((int)val / 10) > 0)
        {
            return value.ToString();
        }
        else 
        {
            return "0" + value.ToString();
        }
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

DayToDayNameConverter

[ValueConversion(typeof(string), typeof(DayOfWeek))]
class DayToDayNameConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return culture.DateTimeFormat.GetDayName((DayOfWeek)value).FirstCharToUpper();
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

MonthToAbbreviatedMonthNameConverter

[ValueConversion(typeof(string), typeof(int))]
class MonthToAbbreviatedMonthNameConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return culture.DateTimeFormat.GetAbbreviatedMonthName((int)value).FirstCharToUpper();
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

MonthToGenitiveMonthNameConverter

[ValueConversion(typeof(string), typeof(int))]
class MonthToGenitiveMonthNameConverter : IValueConverter
{
    private const int ArrayZeroBasedConst = 1;
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    { 
        return culture.DateTimeFormat.MonthGenitiveNames[(int)value - ArrayZeroBasedConst].FirstCharToUpper();
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

MonthToNominativeMonthNameConverter

[ValueConversion(typeof(string), typeof(int))]
class MonthToNominativeMonthNameConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return culture.DateTimeFormat.GetMonthName((int)value).FirstCharToUpper();
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

已排查第三方PopupProperties相关代码,确认无问题。由于无法访问DatePicker和Calendar的内部方法,目前陷入困境,可提供更多代码。


内容的提问来源于stack exchange,提问作者Zero Indefined

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 03:25:16