Cara memformat TimeSpan di XAML

92

Saya mencoba memformat textblock yang terikat ke TimeSpanproperti. Ia bekerja jika properti bertipe DateTimetetapi gagal jika itu adalah TimeSpan. Saya bisa menyelesaikannya menggunakan konverter. Tetapi saya mencoba mencari tahu apakah ada alternatif lain.

Kode sampel:

public TimeSpan MyTime { get; set; }

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

Xaml

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

Saya mengharapkan textblock hanya menampilkan jam dan menit. Tapi itu ditampilkan sebagai:

19: 10: 46.8048860

biju
sumber
Apakah Anda ingat versi .Net yang Anda gunakan pada tahun 2010? Saya mengalami masalah serupa dengan Windows Phone XAML: stackoverflow.com/q/18679365/1001985
McGarnagle
Catatan: {} di awal semua format adalah escape sequence, bukan penentu format. Ini menyebabkan XAML mentolerir tanda kurung lebih lanjut dalam format, tanpa memerlukan garis miring terbalik.
Grault

Jawaban:

88

Di .NET 3.5 Anda bisa menggunakan MultiBinding sebagai gantinya

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

Perbarui
Untuk menjawab komentar.

Untuk memastikan Anda mengeluarkan 2 digit meskipun jam atau menit adalah 0-9 Anda dapat menggunakan {0:00} alih-alih {0}. Ini akan memastikan output untuk waktu 12:01 adalah 12:01, bukan 12: 1.
Jika Anda ingin menghasilkan 01:01 sebagai 1:01 gunakanStringFormat="{}{0}:{1:00}"

Dan pemformatan bersyarat dapat digunakan untuk menghilangkan tanda negatif selama beberapa menit. Alih-alih {1:00} kita dapat menggunakan {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>
Fredrik Hedblad
sumber
@chibacity: Terima kasih! Saya telah memberikan kredit pada jawaban Anda sehingga saya tidak dapat melakukannya lagi :) Tetapi saya lebih menyukai pertanyaan tersebut sehingga saya dapat menemukan kembali solusi Anda jika saya membutuhkannya! Sangat bagus juga
Fredrik Hedblad
1
Bukankah ini akan menghasilkan "10: 1" atau "4: 9" jika bagian menit hanya memiliki satu digit?
Cygon
@Cygon: Lihat jawaban terbaru saya untuk cara mengatasinya. Gunakan {0: D2} alih-alih {0}
Fredrik Hedblad
Ini menghasilkan "-07: -12" untuk Timedur negatif 7 jam dan 12 menit. jika durasinya minus 7 jam, outputnya adalah "-07: 00". Tapi begitu ada menit bukan nol pada durasi negatif, minus ditambahkan .Hourske.Minutes
tzippy
@FredrikHedblad Saya ingin menunjukkan TotalMinutesbukan Minutessebagai bagian menit (untuk menunjukkan rentang waktu terlama 1 jam itu). Tetapi TotalMinutesproperti dalam format ganda, jadi mengikat menggunakan <Binding Path="MyTime.TotalMinutes" />menghasilkan keluaran bulat, yang buruk - saya perlu menunjukkan nilai terpotong daripada dibulatkan. Dimungkinkan untuk mencapainya tanpa menggunakan coneverter nilai kustom untuk memotong double ke int?
Dominik Palo
140

Format string dimaksudkan untuk bekerja pada a DateTime, bukan a TimeSpan.

DateTime.NowSebagai gantinya, Anda dapat mengubah kode Anda untuk digunakan . Xaml Anda baik-baik saja:

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

Memperbarui

Dan dari .Net 4 format a TimeSpansebagai berikut:

<TextBlock Text="{Binding MyTime,StringFormat=hh\\:mm}"/>
Tim Lloyd
sumber
Ya ... Tetapi saya mencari cara agar saya dapat memformat nilai Jangka Waktu.
biju
1
Saya memfilter bagian waktu saya dari kumpulan tanggal, mengambil yang berbeda, menyortir..blah.. begitulah logika saya
biju
@biju Saya telah memperbarui sampel dengan string format untuk TimeSpan.
Tim Lloyd
2
Saya tidak tahu apakah saya melakukan sesuatu yang salah .. tetapi masih tidak berfungsi untuk saya di sini.VisualStudio 2008, Framework 3.5
biju
1
Ini adalah jawaban yang benar, bukan yang ditandai di atas. Bahkan untuk dot net 3.5 gunakan konverter alih-alih jawaban yang disarankan.
MikeKulls
45

Hanya untuk menambahkan ke kumpulan, saya berhasil menggunakan pengikatan ini untuk menampilkan TimeSpan di aplikasi WPF produksi:

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

Mengambil beberapa percobaan untuk mendapatkan garis miring terbalik dengan benar :)

Cygon
sumber
5
Jika Anda ingin beralih ke sepersekian detik, Anda juga perlu menghilangkan koma: {0: hh \\: mm \\: ss \\.
Ffff

StringFormat = \ {0: hh \\: mm \\: ss \\. Fff \}
Stepan Ivanenko
Kesalahan besar saya sepanjang waktu adalah saya menggunakan H seperti format string DateTime. Tapi jelas tidak ada format 12/24 untuk TimeSpan ...
M Stoerzel
22

StringFormatharus dalam bentuk string format. Dalam hal ini akan terlihat seperti:

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

Catatan: jika Anda ingin menampilkan jumlah total jam dan menit dan rentang waktunya lebih dari 24 jam, ada peringatan dengan pendekatan Anda: Berikut solusinya .

Peter Lillevold
sumber
@biju - sintaks yang diperbarui. Tidak ada tanda kutip tunggal di sekitar nilai StringFormat.
Peter Lillevold
Dan ya, seperti yang ditunjukkan contoh @chibacity, tanda ganda \ diperlukan untuk keluar dari:
Peter Lillevold
1
dan memang, ini hanya berfungsi di .Net 4.0! String format benar-benar diabaikan di .Net 3.5.
Peter Lillevold
2
Juga perhatikan bahwa ini berfungsi dengan TextBlock tetapi TIDAK (!) Dengan Label.
Belenggu
2
@Shackles StringFormat digunakan hanya jika target Binding adalah properti bertipe String. Label.Content adalah Object, jadi diabaikan. TextBlock.Text adalah string, jadi ini digunakan.
15ee8f99-57ff-4f92-890c-b56153
16

Untuk Multi binding, Anda perlu memperhatikan sejak .NET 4.

Gambaran singkat di bawah ini, diuji dengan .NET 4.6:

Penjilidan biasa:

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

Multi mengikat:

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

atau Anda dapat menggunakan " alih-alih ' dalam multi-binding:

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

Catatan: menggunakan StringFormat = "{} {0: hh \: \: mm \: ss} -> {1: hh \: mm \: ss}" tidak akan berfungsi pada MultiBinding, ini akan menghasilkan hasil kosong.

juFo
sumber
13

Saya sadar bahwa pertanyaan ini sudah tua sekarang, tetapi saya terkejut bahwa tidak ada yang menyarankan hal sederhana ini StringFormatyang akan bekerja secara TimeSpanlangsung:

<TextBlock Text="{Binding MyTime, StringFormat={}{0:hh}:{0:mm}, FallbackValue=00:00}"/>
Sheridan
sumber
2
Banyak kebingungan seputar ini. Sepertinya mungkin sintaksnya berubah dengan .NET 4.
McGarnagle
12

WPF di .NET 4 sekarang memiliki rentang waktu dari string http://msdn.microsoft.com/en-us/library/ee372286.aspx

Saya menggunakan yang berikut ini <TextBlock FontSize="12" Text="{Binding Path=TimeLeft, StringFormat={}{0:g}}" />

Ira
sumber
1
Sebenarnya bekerja di .NET 4-4.5. Tidak ada solusi lain di utas ini yang dapat melakukannya.
erodewald
Mungkin itu benar pada Februari 2012, tapi sekarang tidak lagi.
Sheridan
8

Jika Anda ingin menggunakan StringFormat dalam Label yang menggunakan properti Konten, Anda dapat menggunakan ContentStringFormat untuk memformat rentang waktu Anda:

<Label Content={Binding MyTimespan}" ContentStringFormat="{}{0:hh}:{0:mm}:{0:ss}"
mcflux101
sumber
Apa yang Anda nyatakan dalam jawaban Anda layak mendapat sorotan ganda: dalam kontrol XAML yang menggunakan Contentproperti (yaitu, bukan Textproperti karena, misalnya, a TextBlock), properti ContentStringFormat harus digunakan. Menentukan StringFormatsebagai bagian dari pengikatan tidak akan berfungsi.
Informagic
2

TimeSpan StringFormat dengan milidetik:

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