So formatieren Sie TimeSpan in XAML


92

Ich versuche, einen Textblock zu formatieren, der an eine TimeSpanEigenschaft gebunden ist . Es funktioniert, wenn die Eigenschaft vom Typ ist, DateTimeaber es schlägt fehl, wenn es eine ist TimeSpan. Ich kann es mit einem Konverter erledigen. Aber ich versuche herauszufinden, ob es Alternativen gibt.

Beispielcode:

public TimeSpan MyTime { get; set; }

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

Xaml

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

Ich erwarte, dass der Textblock nur Stunden und Minuten anzeigt. Aber es zeigt sich als:

19: 10: 46.8048860


Erinnerst du dich, welche Version von .Net du 2010 auf dem Weg ausgeführt hast? Ich habe ein ähnliches Problem mit Windows Phone XAML: stackoverflow.com/q/18679365/1001985
McGarnagle

Hinweis: Das {} am Anfang aller Formate ist eine Escape-Sequenz, kein Formatbezeichner. Dadurch toleriert XAML weitere Klammern im Format, ohne dass Backslashes erforderlich sind.
Grault

Antworten:


88

In .NET 3.5 können Sie stattdessen ein MultiBinding verwenden

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

Update
Um die Kommentare zu beantworten.

Um sicherzustellen, dass Sie 2 Ziffern ausgeben, auch wenn Stunden oder Minuten 0-9 sind, können Sie {0:00} anstelle von {0} verwenden. Dadurch wird sichergestellt, dass die Ausgabe für die Zeit 12:01 12:01 statt 12: 1 ist.
Wenn Sie 01:01 als 1:01 ausgeben möchten, verwenden SieStringFormat="{}{0}:{1:00}"

Die bedingte Formatierung kann verwendet werden, um das negative Vorzeichen für Minuten zu entfernen. Anstelle von {1:00} können wir {1: 00; 00} verwenden

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

@chibacity: Danke! Ich habe Ihre Antwort bereits gutgeschrieben, damit ich sie nicht noch einmal machen kann :) Aber ich habe die Frage favorisiert, damit ich zu Ihrer Lösung zurückkehren kann, falls ich sie jemals brauchte! Sehr schön auch
Fredrik Hedblad

1
Würde dies nicht "10: 1" oder "4: 9" ausgeben, wenn der Minutenteil nur eine Ziffer hat?
Cygon

@Cygon: In meiner aktualisierten Antwort erfahren Sie, wie Sie dies beheben können. Verwenden Sie {0: D2} anstelle von {0}
Fredrik Hedblad

Dies gibt "-07: -12" für eine negative Zeitdauer von 7 Stunden und 12 Minuten aus. Wenn die Dauer minus 7 Stunden beträgt, wäre die Ausgabe "-07: 00". Aber sobald es eine Minute ungleich Null mit einer negativen Dauer gibt, wird das Minus sowohl an .Hoursals auch an.Minutes
tzippy

@FredrikHedblad Ich möchte TotalMinutesanstelle von MinutesMinuten anzeigen (um Zeiträume anzuzeigen, die am längsten diese 1 Stunde sind). Da die TotalMinutesEigenschaft jedoch im doppelten Format vorliegt, führt das Binden mit der <Binding Path="MyTime.TotalMinutes" />Ausgabe zu einer gerundeten Ausgabe, was schlecht ist. Ich muss einen abgeschnittenen Wert anstelle eines gerundeten Werts anzeigen. Es ist möglich, dies zu erreichen, ohne einen benutzerdefinierten Wertekonverter zum Abschneiden von double auf int zu verwenden.
Dominik Palo

139

Die Formatzeichenfolge soll auf a DateTimeund nicht auf a funktionieren TimeSpan.

Sie können DateTime.Nowstattdessen Ihren Code ändern, um damit zu arbeiten . Dein xaml ist in Ordnung:

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

Aktualisieren

Und aus dem .Net 4- Format a TimeSpanwie folgt:

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

Ja ... Aber ich suche nach einer Möglichkeit, einen Timespan-Wert zu formatieren.
Biju

1
Ich filtere meinen Zeitteil aus einer Sammlung von Daten, nehme verschiedene, sortiere ... bla ... es ist der Weg, den meine Logik geht
Biju

@biju Ich habe das Beispiel mit einer Formatzeichenfolge für TimeSpan aktualisiert.
Tim Lloyd

2
Ich weiß nicht, ob ich etwas falsch mache ... aber es funktioniert hier immer noch nicht für mich. VisualStudio 2008, Framework 3.5
Biju

1
Dies ist die richtige Antwort, nicht die oben markierte. Verwenden Sie auch für dot net 3.5 einen Konverter anstelle der vorgeschlagenen Antwort.
MikeKulls

44

Um den Pool zu erweitern, verwende ich diese Bindung erfolgreich, um einen TimeSpan in einer Produktions-WPF-App anzuzeigen:

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

Hat einige Versuche unternommen, um die Backslashes richtig zu machen :)


5
Wenn Sie zu Sekundenbruchteilen gehen möchten, müssen Sie auch dem Komma entkommen: {0: hh \\: mm \\: ss \\. Ffff}
Rashack

StringFormat = \ {0: hh \\: mm \\: ss \\. Fff \}
Stepan Ivanenko

Mein großer Fehler war die ganze Zeit, dass ich eine Zeichenfolge im H-ähnlichen DateTime-Format verwendet habe. Aber offensichtlich gibt es kein 12/24-Format für TimeSpan ...
M Stoerzel

22

StringFormatmuss in Form einer Formatzeichenfolge vorliegen. In diesem Fall würde es so aussehen:

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

Hinweis: Wenn Sie die Gesamtzahl der Stunden und Minuten anzeigen möchten und die Zeitspanne mehr als 24 Stunden beträgt, gibt es eine Einschränkung bei Ihrem Ansatz: Hier ist eine Problemumgehung .


@biju - aktualisierte Syntax. Es fehlten einfache Anführungszeichen um den StringFormat-Wert.
Peter Lillevold

Und ja, wie das Beispiel @chibacity zeigt, ist ein doppeltes \ erforderlich, um dem:
Peter Lillevold

1
und tatsächlich funktioniert dies nur in .Net 4.0! Die Formatzeichenfolge wird in .Net 3.5 vollständig ignoriert.
Peter Lillevold

2
Beachten Sie auch, dass dies mit einem TextBlock funktioniert, jedoch NICHT (!) Mit einem Label.
Fesseln

2
@Shackles StringFormat wird nur verwendet, wenn das Ziel der Bindung eine Eigenschaft vom Typ String ist. Label.Content ist Object und wird daher ignoriert. TextBlock.Text ist eine Zeichenfolge und wird daher verwendet.
15ee8f99-57ff-4f92-890c-b56153

16

Bei Mehrfachbindungen müssen Sie seit .NET 4 aufpassen.

Eine kurze Übersicht unten, getestet mit .NET 4.6:

Regelmäßige Bindung:

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

Mehrfachbindung:

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

oder Sie könnten " anstelle von " in der Multibindung verwenden:

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

Hinweis: Die Verwendung String = "{} {0: hh \: \: mm \: ss} -> {1: hh \: mm \: ss}" wird nicht die Arbeit an einem Multibinding, wird dies in einem leeren Ergebnis führen.


13

Ich bin mir bewusst, dass diese Frage jetzt alt ist, aber ich bin überrascht, dass niemand diese einfache Frage vorgeschlagen hat, StringFormatdie TimeSpandirekt auf eine :

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

2
Viel Verwirrung darüber. Scheint, als hätte sich die Syntax mit .NET 4 geändert.
McGarnagle


8

Wenn Sie StringFormat in einem Label verwenden möchten, das die Content-Eigenschaft verwendet, können Sie ContentStringFormat zum Formatieren Ihrer Zeitspanne verwenden:

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

Was Sie in Ihrer Antwort angeben, verdient eine doppelte Hervorhebung: In XAML-Steuerelementen, die die ContentEigenschaft verwenden (dh nicht die TextEigenschaft wie z. B. a TextBlock), ContentStringFormat muss die Eigenschaft verwendet werden. Die Angabe StringFormatals Teil der Bindung funktioniert nicht.
Informagic

2

TimeSpan StringFormat mit Millisekunden:

<TextBlock Text="{Binding MyTime, StringFormat=\{0:hh\\:mm\\:ss\\.fff\}}"/>
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.