更改WPF日历控件日名称格式

时间:2013-10-15 09:06:31

标签: wpf calendar string-formatting

我目前正在使用WPF日历控件。日名称显示为Su,Mo,Tu等。但我希望这些名称显示为Sun,Mon,Tue等。我发现没有数据模板属性来实现这个。

任何建议都将不胜感激。

由于

5 个答案:

答案 0 :(得分:1)

我已经调查了这一点,不幸的是,我认为你无法达到你想要的效果。

首先,我发现StringFormat在MSDN的Custom Date and Time Format Strings页面显示三个字符日名称:

StringFormat=ddd

然后我认为您可以在Custom date format for WPF Calendar CalendarItems帖子中找到解决其余问题的方法。因此,调整@Quartermeister的想法,我可以尝试以下方法:

<Calendar>
    <Calendar.CalendarButtonStyle>
        <Style TargetType="primitives:CalendarButton">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="primitives:CalendarButton">
                        <primitives:CalendarButton>
                            <TextBlock Text="{Binding Day, StringFormat=ddd}"/>
                        </primitives:CalendarButton>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Calendar.CalendarButtonStyle>
</Calendar>

你可以想象,我离开了,因为这回答了另一个问题。所以我回到MSDN找the default ControlTemplate for the Calendar control进一步试验。如果您查看ControlTemplate,则会看到名为Style的{​​{1}}。

由于CalendarItemStyleStyle并且在ControlTemplate部分,您会看到Resources,其中包含密钥DataTemplate。最后,在{x:Static CalendarItem.DayTitleTemplateResourceKey}中,您会看到负责显示日期名称的DataTemplate

TextBlock

我增加了日期名称的大小,因此我们可以确定这是正确的<TextBlock Foreground="#FF333333" FontWeight="Bold" FontSize="9.5" FontFamily="Verdana" Margin="0,6,0,6" Text="{Binding}" HorizontalAlignment="Center" VerticalAlignment="Center" /> 。 (忽略顶部奇怪的TextBlock - 他们就是这样,因为我没有复制他们的Button s:

enter image description here

现在,如果您查看ControlTemplate中的Binding,您会看到不幸的是,它被设置为TextBlock。这意味着它使用整个数据绑定值,而不是在{Binding}对象上设置特定的StringFormat。这意味着我们无法使用DateTime,因为数据绑定值已经是StringFormat

答案 1 :(得分:1)

最后,我用以下转换器解决了它,

public class CalendarDayNameConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        var daynames = CultureInfo.CurrentCulture.DateTimeFormat.DayNames;
        string dayname = value.ToString();

        return daynames.First(t => t.StartsWith(dayname)).Substring(0, 3);
    }

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

答案 2 :(得分:0)

我也一直在研究它。

我见过的唯一解决方案是使用自定义本地化字典本地化日历,但遗憾的是没有给出密钥,我们可以使用。

重新编译我发现的日历控件,日历控件使用本机函数(nativeGetCalendarData())来本地化日历,因此我无法以简单的方式检索这些键:(

答案 3 :(得分:0)

请参阅此网站nullskull.com。可下载源包含日期名称转换器和说明

答案 4 :(得分:0)

在这里晚了聚会,但是我想出了一个稍微不同的解决方案,希望它将在国际上更加可靠地工作。这是两部分的事情。首先,按照上面@Sheridan所述,为日期名称制作一个模板:

<DataTemplate x:Key="{x:Static CalendarItem.DayTitleTemplateResourceKey}">
    <TextBlock>
        <TextBlock.Text>
            <MultiBinding Converter="{StaticResource CalendarDayNameConverter}">
                <Binding Path="(Grid.Column)" RelativeSource="{RelativeSource Self}" Mode="OneWay"/>
                <Binding Path="FirstDayOfWeek" RelativeSource="{RelativeSource AncestorType={x:Type Calendar}}" Mode="OneWay"/>
            </MultiBinding>
        </TextBlock.Text>
    </TextBlock>
</DataTemplate>

当然,请根据您的要求进行格式化。这里的技巧是将Text绑定到Grid.Column而不是通常的数据上下文值(WPF提供的两个字母的天名称)。网格列号由内部WPF logic设置,应该可靠。我们必须使用IMultiValueConverter,因为我们也依赖于父FirstDayOfWeek控件的Calendar值:

public sealed class CalendarDayNameConverter : IMultiValueConverter
{
    /// <inheritdoc/>
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        if (values?.Length > 0 && values[0] is int index)
        {
            var dayNames = culture?.DateTimeFormat?.AbbreviatedDayNames;
            if (dayNames?.Length > 0)
            {
                var firstDayOfWeek = values.Length > 1 && values[1] is DayOfWeek d ? d : culture.DateTimeFormat.FirstDayOfWeek;
                return dayNames[(index + (int)firstDayOfWeek) % dayNames.Length];
            }
        }

        return DependencyProperty.UnsetValue;
    }

    /// <inheritdoc/>
    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) =>
        null;
}