如何在 XAML 中设置 TimeSpan 格式

发布于 2024-10-09 21:32:53 字数 533 浏览 0 评论 0原文

我正在尝试格式化绑定到 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

I am trying to format a textblock which is bound to a TimeSpan property. It works if the property is of type DateTime but it fails if it is a TimeSpan. I can get it done using a converter. But I am trying to find out if there is any alternatives.

Sample Code:

public TimeSpan MyTime { get; set; }

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

Xaml

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

I am expecting the textblock to show only hours and mintes. But it is showing as:

19:10:46.8048860

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

过期以后 2024-10-16 21:32:53

格式字符串适用于 DateTime,而不是 TimeSpan

您可以更改代码以使用 DateTime.Now 来代替。你的xaml没问题:

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

更新

来自.Net 4< /a> 格式化 TimeSpan 如下:

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

The format string is intended to work on a DateTime, not a TimeSpan.

You could change your code to work with DateTime.Now instead. Your xaml is fine:

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

Update

And from .Net 4 format a TimeSpan as follows:

<TextBlock Text="{Binding MyTime,StringFormat=hh\\:mm}"/>
挽心 2024-10-16 21:32:53

在 .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>

In .NET 3.5 you could use a MultiBinding instead

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

Update
To answer the comments.

To make sure you output 2 digits even if hours or minutes is 0-9 you can use {0:00} instead of {0}. This will make sure the output for the time 12:01 is 12:01 instead of 12:1.
If you want to output 01:01 as 1:01 use StringFormat="{}{0}:{1:00}"

And Conditional formatting can be used to remove the negative sign for minutes. Instead of {1:00} we can use {1:00;00}

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

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

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

做了一些尝试才得到正确的反斜杠:)

Just to add to the pool, I'm successfully using this binding to display a TimeSpan in a production WPF app:

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

Took some tries to get the backslashes right :)

随波逐流 2024-10-16 21:32:53

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

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

If you want to use StringFormat in a Label that uses the Content property, you can use ContentStringFormat to format your timespan:

<Label Content={Binding MyTimespan}" ContentStringFormat="{}{0:hh}:{0:mm}:{0:ss}"
稀香 2024-10-16 21:32:53

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

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

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

StringFormat must be in the form of a format string. In this case it would look like:

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

Note: if you want to display the total number of hours and minutes and the timespan happens to be greater than 24 hours, there's a caveat with your approach: Here's a workaround.

花之痕靓丽 2024-10-16 21:32:53

对于多重绑定,您需要从 .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 上工作,这将导致空白结果。

For Multi bindings you need to pay attention since .NET 4.

A short overview below, tested with .NET 4.6:

Regular binding:

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

Multi binding:

<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>

or you could use " instead of ' in the multibinding:

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

Note:
using StringFormat="{}{0:hh\:\:mm\:ss} -> {1:hh\:mm\:ss}" will not work on a MultiBinding, this will result in a blank result.

做个ˇ局外人 2024-10-16 21:32:53

我知道这个问题现在已经很老了,但令我惊讶的是没有人建议这个简单的 StringFormat 直接在 TimeSpan 上工作:

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

I'm aware that this question is old now, but I'm surprised that no one suggested this simple StringFormat which will work on a TimeSpan directly:

<TextBlock Text="{Binding MyTime, StringFormat={}{0:hh}:{0:mm}, FallbackValue=00:00}"/>
少钕鈤記 2024-10-16 21:32:53

.NET 4 中的 WPF 现在具有来自字符串的时间跨度 http://msdn.microsoft.com /en-us/library/ee372286.aspx

我正在使用以下

WPF in .NET 4 now has timespan from strings http://msdn.microsoft.com/en-us/library/ee372286.aspx

I am using the following <TextBlock FontSize="12" Text="{Binding Path=TimeLeft, StringFormat={}{0:g}}" />

标点 2024-10-16 21:32:53

TimeSpan StringFormat 以毫秒为单位:

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

TimeSpan StringFormat with milliseconds:

<TextBlock Text="{Binding MyTime, StringFormat=\{0:hh\\:mm\\:ss\\.fff\}}"/>
青萝楚歌 2024-10-16 21:32:53

Mi的解决方案是这样的:(

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

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

Mi solutions was this:

(duplicate the element 0 as many times you need)

<TextBlock Text="{Binding MyTime, StringFormat='{0:hh}:{0:mm}'}"/>
明媚如初 2024-10-16 21:32:53

这里有一些 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% 适合关于什么是可能的“其他”替代方案的问题。但是,我希望将其留在这里,因为许多人可能会发现这是一种有用的方法。

There are some StringFormat options working here - but if you want to have total freedom of TimeSpan to string conversion, while remaining well within clean XAML style, there is also the option of creating a simple 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
    }
}

then, its possible to have, for example a StaticResource in a user control :

<UserControl.Resources>
    <local:TimespanToSpecialStringConverter x:Key="TimespanToSpecialStringConverter" />
</UserControl.Resources>

and finally apply the TimespanToSpecialStringConverter within a typical databinding :

<TextBlock Text="{Binding Path=ATimespanDependencyProperty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource TimespanToSpecialStringConverter}}" />

Now you can programatically change the string conversion to your needs while having clean XAML :) Remember, this is only another option if you need full flexibility.

PS: Now I have read, that you were already using a Converter. So this answer does not 100% fit to the question about what 'other' alternatives are possible. However, I hope it is left here, since many people might find this a usefull way to go.

酒绊 2024-10-16 21:32:53

如果你可以不用使用标签,我发现这有效(摆脱小数秒)。 TimeOff 的类型是 TimeSpan:

 <Label     Content="{Binding TimeOff}"  ContentStringFormat="{}{0:%d}:{0:%h}:{0:%m}:{0:%s}" />

ContentStringFormat 在 TextBlocks 中不可用,这对您来说很不幸......

If you can get away with using a Label, I found this works (to get rid of fractional seconds). TimeOff's type is TimeSpan:

 <Label     Content="{Binding TimeOff}"  ContentStringFormat="{}{0:%d}:{0:%h}:{0:%m}:{0:%s}" />

ContentStringFormat is not available in TextBlocks unfortunate for you...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文