web-dev-qa-db-ja.com

WPF XAML StringFormat DateTime:間違ったカルチャで出力しますか?

DateTime値の出力に問題があります。私のコンピューターの現在の文化はde-AT(オーストリア)に設定されています。

次のコード

string s1 = DateTime.Now.ToString("d");
string s2 = string.Format("{0:d}", DateTime.Now);

s1とs2の両方が「30.06.2009」の正しい値になります。

ただし、XAMLで同じ形式を使用する場合

    <TextBlock Text="{Binding Source={x:Static sys:DateTime.Now}, StringFormat=d}"/>

出力は `" 6/30/2009 "です。 XAML StringFormatは現在のカルチャ設定を無視しているようです。これはVistaとXPの両方で発生します。

出力はユーザーの好みのカルチャ設定でフォーマットする必要があるため、カスタムフォーマットを指定したくありません。

同じ問題を抱えている人はいますか?これはWPFのバグですか?

61
42
loraderon

http://tinyurl.com/b2jegna に記載されているソリューションを適用するには、次の手順を実行します。

(1)スタートアップイベントハンドラーをapp.xamlのApplicationクラスに追加します。

<Application x:Class="MyApp"
    xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
    ...
    Startup="ApplicationStartup">

(2)ハンドラー関数を追加します。

private void ApplicationStartup(object sender, StartupEventArgs e)
{
    FrameworkElement.LanguageProperty.OverrideMetadata(
        typeof(FrameworkElement),
        new FrameworkPropertyMetadata(XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag)));
}

WPF文字列は、カルチャに従って正しくフォーマットされる必要があります。

14
Stephen Holt

しばらく前に私のブログでそれについて書いた:

これにより、WPFで適切なカルチャを使用する方法がわかります。

http://www.nbdtech.com/blog/archive/2009/02/22/wpf-data-binding-cheat-sheet-update-the-internationalization-fix.aspx

コントロールパネルの設定を変更すると、WPFカルチャがその場で変更されます。

http://www.nbdtech.com/blog/archive/2009/03/18/getting-a-wpf-application-to-pick-up-the-correct-regional.aspx

10
Nir

特定の言語が1つ必要な場合は、xml:langを使用して最上位要素に設定できます。

例えば:

<Window xml:lang="de-AT">
...
</Window>
4
Domysee

これは高齢化の問題であることを知っていますが、これは私にとって常に有効であり、知識を共有することは良いことです。私のアプリは常にオンザフライで言語を変更するため、FrameworkElement.LanguageProperty.OverrideMetadataは1回しか機能せず、私にとっては役に立たないので、注意してください。

this.Language = System.Windows.Markup.XmlLanguage.GetLanguage(ActiveLanguage.CultureInfo.IetfLanguageTag);

ここ(これ)はMainWindowであり、実際にはすべてのルート要素(Windows)で実行する必要があります。そこまで簡単です。

3
Nemesis

iValueConverter(カルチャパラメーターを受け取る)を使用して、必要に応じて値を書式設定できます。私が気に入っているのは、マットハミルトンによるこのNULL可能コンバーターです

class NullableDateTimeConverter : ValidationRule, IValueConverter
{
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
    if (value == null || value.ToString().Trim().Length == 0) return null;

    return new ValidationResult( 
        ConvertBack(value, typeof(DateTime?), null, cultureInfo) != DependencyProperty.UnsetValue,
        "Please enter a valid date, or leave this value blank");
}

#region IValueConverter Members
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
    if (value == null) return "";
    DateTime? dt = value as DateTime?;
    if (dt.HasValue)
    {
        return parameter == null ? dt.Value.ToString() : dt.Value.ToString(parameter.ToString());
    }
    return ""; 
} 

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
    if (value == null || value.ToString().Trim().Length == 0) return null;
    string s = value.ToString();

    if (s.CompareTo("today") == 0) return DateTime.Today;
    if (s.CompareTo("now") == 0) return DateTime.Now;
    if (s.CompareTo("yesterday") == 0) return DateTime.Today.AddDays(-1);
    if (s.CompareTo("tomorrow") == 0) return DateTime.Today.AddDays(1);

    DateTime dt; 
    if (DateTime.TryParse(value.ToString(), out dt)) return dt; 

    return DependencyProperty.UnsetValue; 
}  
#endregion

}

heres the original

1
almog.ori