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

Biju
quelle
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>
Fredrik Hedblad
quelle
@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}"/>
Tim Lloyd
quelle
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 :)

Cygon
quelle
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 .

Peter Lillevold
quelle
@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.

juFo
quelle
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}"/>
Sheridan
quelle
2
Viel Verwirrung darüber. Scheint, als hätte sich die Syntax mit .NET 4 geändert.
McGarnagle
12

WPF in .NET 4 hat jetzt eine Zeitspanne von Zeichenfolgen http://msdn.microsoft.com/en-us/library/ee372286.aspx

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

Ira
quelle
1
Funktioniert tatsächlich in .NET 4-4.5. Keine anderen Lösungen in diesem Thread.
Erodierwald
Vielleicht stimmte das im Februar 2012, aber es ist nicht mehr so.
Sheridan
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}"
mcflux101
quelle
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\}}"/>
Stepan Ivanenko
quelle