如何在 XAML 中格式化 TimeSpan

问题描述 投票:0回答:12

我正在尝试格式化绑定到

TimeSpan
属性的文本块。如果属性是
DateTime
类型,则有效,但如果是
TimeSpan
类型,则失败。我可以使用转换器来完成它。但我正在尝试找出是否有其他选择。

示例代码:

public TimeSpan MyTime { get; set; }

public Window2()
{
    InitializeComponent();
    MyTime = DateTime.Now.TimeOfDay;
    DataContext = this;
}

Xaml

<TextBlock Text="{Binding MyTime,StringFormat=HH:mm}"/>

我希望文本块仅显示小时和分钟。但它显示为:

19:10:46.8048860

c# wpf xaml data-binding string-formatting
12个回答
164
投票

格式字符串适用于

DateTime
,而不是
TimeSpan

您可以更改代码以使用

DateTime.Now
来代替。你的xaml没问题:

<TextBlock Text="{Binding MyTime,StringFormat=HH:mm}"/>

更新

并从 .Net 4 格式化

TimeSpan
,如下所示:

<TextBlock Text="{Binding MyTime,StringFormat=hh\\:mm}"/>

99
投票

在 .NET 3.5 中,您可以使用 MultiBinding 来代替

<TextBlock>
    <TextBlock.Text>
        <MultiBinding StringFormat="{}{0}:{1}">
            <Binding Path="MyTime.Hours"/>
            <Binding Path="MyTime.Minutes"/>
        </MultiBinding>
    </TextBlock.Text>
</TextBlock>

更新
回复评论。

为了确保输出 2 位数字,即使小时或分钟是 0-9,您也可以使用 {0:00} 而不是 {0}。这将确保时间 12:01 的输出是 12:01 而不是 12:1。
如果要将 01:01 输出为 1:01,请使用

StringFormat="{}{0}:{1:00}"

条件格式可用于删除几分钟的负号。我们可以使用 {1:00;00} 代替 {1:00}

<TextBlock>
    <TextBlock.Text>
        <MultiBinding StringFormat="{}{0:00}:{1:00;00}">
            <Binding Path="MyTime.Hours" />
            <Binding Path="MyTime.Minutes" />
        </MultiBinding>
    </TextBlock.Text>
</TextBlock>

53
投票

为了添加到池中,我成功地使用此绑定在生产 WPF 应用程序中显示 TimeSpan:

Binding="{Binding Time, Mode=TwoWay, StringFormat=\{0:h\\:mm\}}"

做了一些尝试才使反斜杠正确:)


24
投票

如果您想在使用 Content 属性的标签中使用 StringFormat,您可以使用 ContentStringFormat 来格式化您的时间跨度:

<Label Content={Binding MyTimespan}" ContentStringFormat="{}{0:hh}:{0:mm}:{0:ss}"

21
投票

StringFormat
必须采用格式字符串的形式。在这种情况下,它看起来像:

<TextBlock Text="{Binding MyTime,StringFormat=`Time values are {0:hh\\:mm}`}"/>

注意:如果您想显示总小时数和分钟数,并且时间跨度恰好大于 24 小时,则您的方法有一个警告:这里有一个解决方法


20
投票

从 .NET 4 开始,对于多重绑定需要注意。

下面是使用 .NET 4.6 进行测试的简短概述:

常规装订:

<TextBlock Text="{Binding Start, StringFormat='{}{0:hh\\:mm\\:ss}'}" />

多重绑定:

<TextBlock.Text>
    <MultiBinding StringFormat="{}{0:hh':'mm':'ss} -> {1:hh':'mm':'ss}">
        <Binding Path="Start" Mode="OneWay" UpdateSourceTrigger="PropertyChanged" />
        <Binding Path="End" Mode="OneWay" UpdateSourceTrigger="PropertyChanged" />
    </MultiBinding>
</TextBlock.Text>

或者您可以在多重绑定中使用 " 代替 ':

<MultiBinding StringFormat='{}{0:hh":"mm":"ss} -> {1:hh":"mm":"ss}'>

注意: 使用 StringFormat="{}{0:hh\:\:mm\:ss} -> {1:hh\:mm\:ss}"不适用于 MultiBinding,这将导致空白结果。


13
投票
我知道这个问题现在已经很老了,但令我惊讶的是没有人建议这个简单的

StringFormat

,它可以直接在
TimeSpan
上工作:

<TextBlock Text="{Binding MyTime, StringFormat={}{0:hh}:{0:mm}, FallbackValue=00:00}"/>
    

12
投票
.NET 4 中的 WPF 现在具有来自字符串的时间跨度

http://msdn.microsoft.com/en-us/library/ee372286.aspx

我正在使用以下

<TextBlock FontSize="12" Text="{Binding Path=TimeLeft, StringFormat={}{0:g}}" />


    


6
投票
TimeSpan StringFormat(以毫秒为单位):

<TextBlock Text="{Binding MyTime, StringFormat=\{0:hh\\:mm\\:ss\\.fff\}}"/>
    

1
投票
Mi的解决方案是这样的:

(根据需要多次复制元素 0)

<TextBlock Text="{Binding MyTime, StringFormat='{0:hh}:{0:mm}'}"/>
    

1
投票
这里有一些 StringFormat 选项 - 但如果您想要完全自由地进行 TimeSpan 到字符串的转换,同时保持干净的 XAML 风格,还可以选择创建一个简单的 IValueConverter :

using System; using System.Windows.Data; namespace Bla { [System.Windows.Data.ValueConversion(typeof(TimeSpan), typeof(string))] public class TimespanToSpecialStringConverter : IValueConverter { #region IValueConverter Members public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { if (targetType != typeof(string)) throw new InvalidOperationException("The target must be a string"); var timeSpan = (TimeSpan)value; string minutes = timeSpan.Minutes < 10 ? "0" + timeSpan.Minutes : ""+timeSpan.Minutes; string seconds = timeSpan.Seconds < 10 ? "0" + timeSpan.Seconds : "" + timeSpan.Seconds; return "" + timeSpan.TotalHours + ":" + minutes + ":" + seconds; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { if (targetType != typeof(TimeSpan)) throw new InvalidOperationException("The target must be a TimeSpan"); return TimeSpan.Zero; } #endregion } }
那么,例如,用户控件中可以有一个 StaticResource :

<UserControl.Resources> <local:TimespanToSpecialStringConverter x:Key="TimespanToSpecialStringConverter" /> </UserControl.Resources>
最后在典型的数据绑定中应用 TimespanToSpecialStringConverter :

<TextBlock Text="{Binding Path=ATimespanDependencyProperty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource TimespanToSpecialStringConverter}}" />
现在,您可以根据需要以编程方式更改字符串转换,同时拥有干净的 XAML :) 请记住,如果您需要完全的灵活性,这只是另一个选择。

PS:现在我了解到,您已经在使用转换器了。因此,这个答案并不 100% 适合关于什么是可能的“其他”替代方案的问题。然而,我希望它留在这里,因为很多人可能会发现这是一个有用的方法。


0
投票
如果你可以不用使用标签,我发现了这个工作(摆脱小数秒):

<Label Content="{Binding TimeOff}" ContentStringFormat="{}{0:%d}:{0:%h}:{0:%m}:{0:%s}" />
不幸的是,ContentStringFormat 在 TextBlocks 中不可用...

© www.soinside.com 2019 - 2024. All rights reserved.