【发布时间】:2013-10-15 09:06:30
【问题描述】:
我目前正在使用 WPF 日历控件。日期名称显示为 Su、Mo、Tu 等。但我希望这些名称显示为 Sun、Mon、Tue 等。我发现没有数据模板属性可以实现这一点。
任何建议将不胜感激。
谢谢
【问题讨论】:
标签: wpf calendar string-formatting
我目前正在使用 WPF 日历控件。日期名称显示为 Su、Mo、Tu 等。但我希望这些名称显示为 Sun、Mon、Tue 等。我发现没有数据模板属性可以实现这一点。
任何建议将不胜感激。
谢谢
【问题讨论】:
标签: wpf calendar string-formatting
最后,我用下面的转换器解决了,
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();
}
}
【讨论】:
我对此进行了调查,但不幸的是,我认为您无法实现您想要的。
首先,我发现 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,您将看到一个名为CalendarItemStyle 的Style。
其中Style 是ControlTemplate,在其Resources 部分中,您将看到带有{x:Static CalendarItem.DayTitleTemplateResourceKey} 键的DataTemplate。最后,在DataTemplate 中,您将看到负责显示日期名称的TextBlock:
<TextBlock Foreground="#FF333333"
FontWeight="Bold"
FontSize="9.5"
FontFamily="Verdana"
Margin="0,6,0,6"
Text="{Binding}"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
我增加了日期名称的大小,因此我们可以确定这是正确的TextBlock。 (忽略顶部奇怪的Buttons - 他们就是这样,因为我没有复制他们的ControlTemplates):
现在,如果您查看TextBlock 中的Binding,您会发现不幸的是,它被设置为{Binding}。这意味着它使用整个数据绑定值,而不是在 DateTime 对象上设置特定的 StringFormat。这意味着我们不能使用StringFormat,因为数据绑定值已经是string。
【讨论】:
我也调查过了。
我见过的唯一解决方案是使用自定义本地化字典本地化日历,但不幸的是没有提供我们可以使用的键。
反编译我发现的日历控件,日历控件使用本机函数(nativeGetCalendarData())来本地化日历,所以我将无法轻松检索这些键:(
【讨论】:
请参阅此网站nullskull.com。可下载源包含日期名称转换器和描述
【讨论】:
在这里聚会迟到了,但我想出了一个稍微不同的解决方案,希望它能在国际上更可靠地工作。这是一个两部分的事情。首先,为上面@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,因为我们也依赖父级Calendar 控件的FirstDayOfWeek 值:
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;
}
【讨论】: