WPF:突出显示日期的一部分

时间:2011-08-03 06:58:35

标签: c# .net wpf

我有一个TextBlock,使用当前文化的标准短日期格式显示日期。

String.Format(culture, "{0:d}", someDate)

现在,产品经理希望以粗体突出显示年份。起初,我认为这很容易;有一次运行绑定到日/月 - 部分,第二次运行到年份部分。

<TextBlock>
  <Run Text="{Binding DayMonthPart}"/>
  <Run FontWeight="Bold" Text="{Binding YearPart}"/>
</TextBlock>

但那不会,因为不同的文化有不同的顺序。有些人把这一年放在第一位,有些人把它放在最后。

那么,我该如何实现呢? 有什么想法吗?

6 个答案:

答案 0 :(得分:6)

这是适用于所有文化的通用解决方案:

var r = new Regex(@"^(?<first>[^y]*?)(?<year>y+)(?<second>[^y]*?)$");
var mc = r.Matches(info.DateTimeFormat.ShortDatePattern);
var f = mc[0].Groups["first"].Value;
var y = mc[0].Groups["year"].Value;
var s = mc[0].Groups["second"].Value;

this.First = string.IsNullOrEmpty(f) ? string.Empty : this.date.ToString(f, info);
this.Year = this.date.ToString(y);
try
{
    this.Second = string.IsNullOrEmpty(s) ? string.Empty : this.date.ToString(s, info);           
}
catch
{
    // fallback: sometimes the last char is just a '.'
    this.Second = s;
}

然后在你的XAML中:

<TextBlock>
    <Run Text="{Binding First, Mode=OneWay}" />
    <Run FontWeight="Bold" Text="{Binding Year, Mode=OneWay}" />
    <Run Text="{Binding Second, Mode=OneWay}" />
</TextBlock>

all cultures of .NET

答案 1 :(得分:2)

您需要支持所有可能的文化吗?如果是的话,那将会有点棘手。我想我会做的是首先根据当前文化将日期格式化为字符串。然后我将从该字符串中提取“year”部分并将其从其他部分中删除。然后你会有两个字符串,如此(瑞典格式):

yearString = "2011";
remainingDateString = "-09-01";

或以美国格式:

yearString = "2011";
remainingDateString = "09/01/";

您还必须检查字符串的“年”部分是在完整日期字符串的结尾还是在开头,然后相应地格式化第一个或第二个<Run>元素。在上面的例子中,瑞典格式的年份部分将在字符串的开头(YYYY-MM-DD),而在美国,它将在最后(MM / DD / YYYY)。我不知道任何西方文化会让年份成为弦乐的中间部分。

免责声明:我对非西方日期格式了解不多,所以我不能说这种方法在世界这个地方的效果如何。

编辑:
至于绑定的东西,类似下面的东西应该工作:

<TextBlock>
    <Run Text="{Binding DatePart1}"
            FontWeight="{Binding DatePart1FontWeight}"></Run>
    <Run Text="{Binding DatePart2}"
            FontWeight="{Binding DatePart2FontWeight}"></Run>
</TextBlock>

答案 2 :(得分:0)

你需要使用2个texblocks,或者文本块和标签,因为你不能用另一种字体样式制作相同控件的字符串的一部分(字体及其所有属性对于textblock都是相同的,例如在属性中看到它)。或者你可以在readonly模式下使用一些richedit控件(RichTextBox,只需将格式化的文本传递给它)

答案 3 :(得分:0)

您可以使用开关案例,然后根据所选的文化安排年 - 月 - 日。

switch ( integral or string expression )
{
case constant-expression:
Statements
break
...
default :
Statements
break
}

puesdoCode示例

Read countryOfOrigin
Switch(countryOfOrigin)
Cases of ‘New Zealand’ :
Retrieve(“day-month-**year**”)
Cases of ‘Singapore’, ‘Malaysia’, ... :
Retrieve(“month-**year**-day”)
Cases of ‘Australia’, ‘Great Britain’, … :
Retrieve(“day-month-**year**”)
Other Cases :
Retrieve(“**year**-month-day”)
End Switch

我修改了puesdoCode,另一个解决方案是将值从3个元素拆分为2个元素(所以如果我有一个完整的值,例如“John-Doe-Smith”,我想要John [THE YEAR] ,在REVERSE中将数组从LEFT中分离出来,最后的结果是eoD-nohJ,然后再从REVERSE中的LEFT中拆分,最后的结果是nohJ然后REVERSE你的最终结果得到John)。你也可以通过创建一个分裂机制来获取“年份”,这取决于年份的位置(这也可以通过用“ - ”字符拆分每个值然后获得拆分中检索到的元素的长度来查找今年你将寻找4个字符的值(2011)。一旦你找到了4个字符(1988)的值,你只需找到这4个字符在字符串中开始的位置。然后检索你的最终结果关闭整数位置。

祝你好运抱歉,如果这听起来很复杂。我确信还有其他方法,但这就是我在SQL-T中的做法,我完全相信在C#中可以采用相同的方式制作算法。

答案 4 :(得分:0)

可悲的是,你的运行顺序和文化代表日期时间字符串的方式是两个不相关的东西,只有你可以把它们联系起来......

  1. 通过“某种方式”攻击C#native DateTime类并查看ToString(IFormatProvider)如何工作(在代码中)并使用类似的东西为您的优势,以便您“知道”文化特定字符串的哪一部分是年份哪一个是Day,从而安排你的运行。

  2. 通过分析文化特定日期时间表示来确定哪个是年份,哪个是日期部分。您可以使用直接匹配,这将适用于不同的日,月和年份部分,例如日期01/03/2011将与“2011年3月3日”直接匹配,因为您可以将03(2011年)与03年和2011年(2011年)明显匹配。但是,如果某些X文化将其表示为“01/01/01”,那么像01/01/2001这样的东西可能会造成麻烦,你不知道哪个是哪个。

  3. 为此,您可以了解您的产品/应用程序可以部署到哪些文化,并通过考虑日期,月份和年份的排序来自行关联日,月和年的排序。

    为您的企业提供最佳服务,如果您有更好的解决方案,请分享。

    : - )

答案 5 :(得分:0)

正如其他人所说,你需要自己构建日期 - 但是你可以通过使用

找出日期的组成方式
Thread.CurrentThread.CurrentCulture.DateTimeFormat.ShortDatePattern

(或DateTimeFormat中的一些其他相关成员)

然后,您可以在代码中构建一个格式正确的日期(即按正确的顺序创建TextBlockRun个对象以生成正确的日期格式)并将它们添加到您的控件中({{1} })

或者 - 这感觉就像在实际需要的工作稍微多一点 - 构建datePlaceholder.Children.Add(etc)YearMonthDay类作为占位符,适当地对数据进行模板化为了使Separator为粗体,然后按正确的顺序将组件日期部分放入Year,并将整个批次投放到ObservableCollection<DatePlaceholders>