【问题标题】:WPF Label and TextBlock show DateTime in different formatWPF Label 和 TextBlock 以不同的格式显示 DateTime
【发布时间】:2023-02-06 05:18:51
【问题描述】:

我开发了一些应用程序。而且我发现了一些与 DateTime 格式相关的奇怪事情。所以我创建了一些测试应用程序来更详细地检查它。 因此,我的测试应用程序具有以下结构:

  1. 只有 Date 属性的自定义对象类:

    public class MyObject
    {
        public DateTime Date { get; private set; }
    
        public MyObject(DateTime date)
        {
            Date = date;
        }
    }
    
    1. 自定义 ViewModel 类:

      public class MyViewModel : INotifyPropertyChanged
      {
              public virtual ICollectionView TableView
              {
                      get => tableView;
                      set
                      {
                              tableView = value;
                              OnPropertyChanged(nameof(TableView));
                      }
              }
      
              public virtual ObservableCollection<MyObject> TableItems
              {
                      get { return tableItems; }
                      set
                      {
                              tableItems = value;
                              OnPropertyChanged(nameof(TableItems));
      
                              TableView = CollectionViewSource.GetDefaultView(tableItems);
                      }
              }
      
              public MyViewModel()
              {
                      var dateTimes = new List<MyObject>() 
                      {
                              new MyObject(DateTime.MinValue),
                              new MyObject(DateTime.Now),
                              new MyObject(DateTime.MaxValue)
                      };
      
                      TableItems = new ObservableCollection<MyObject>(dateTimes);
              }
      
              private ICollectionView tableView;
              private ObservableCollection<MyObject> tableItems;
      
              public event PropertyChangedEventHandler PropertyChanged;
      
              public void OnPropertyChanged([CallerMemberName] string prop = "")
              {
                      if (PropertyChanged != null)
                               PropertyChanged(this, new PropertyChangedEventArgs(prop));
              }
      }
      
    2. 使用 DataGrid 和 ListView 来查看控件。它们都绑定到同一个 TableView 集合:

      <Grid>
         <Grid.RowDefinitions>
             <RowDefinition Height="300"/>
             <RowDefinition Height="300"/>
         </Grid.RowDefinitions>
         <DataGrid ItemsSource="{Binding TableView}">
         </DataGrid>
         <ListView Grid.Row="1" ItemsSource="{Binding TableView}">
             <ListView.ItemTemplate>
                 <HierarchicalDataTemplate>
                     <CheckBox HorizontalContentAlignment="Left" VerticalContentAlignment="Center">
                         <CheckBox.Content>
                             <Label Content="{Binding Date}"/>
                         </CheckBox.Content>
                     </CheckBox>
                 </HierarchicalDataTemplate>
             </ListView.ItemTemplate>
         </ListView>
      </Grid>
      

    在这种情况下,我在表格和列表中看到了不同的日期视图:

    如果我在 ListView 项目模板中将 Label 更改为 TextBlock,我将看到相同的结果:

    为什么会这样?以及如何根据 Culture 日期时间设置在所有控件中显示相同的格式?

【问题讨论】:

  • 日期从 1/1/01 开始,这是 MIN。由于您没有初始化 MIN,因此您得到的是 1/1/01。 MAX 也是如此,即 12/31/9999。要获得不同的格式,请使用 ToString("d/M/yyyy h:mm:ss tt")。

标签: c# wpf datetime


【解决方案1】:

ContentControl(因此也是Label)使用ContentControl.ContentStringFormat属性来格式化string内容,而TextBlockTextBox等文本元素使用FrameworkElement.Language属性,默认为"en-US"

内容控制

ContentControl 的情况下,ContentControl.ContentStringFormat 未明确定义,字符串使用 Thread.CurrentThread.CurrentCulture 格式化为后备 CultureInfo(使用从 CultureInfo.DateTimeFormat 属性返回的 DateTimeFormatInfo)。
在您的情况下,这显然不是“en-US”语言。

如果你想在特定的ContentControl元素上强制使用通用的日期格式,你可以使用一个命名的Style来设置ContentControl.ContentStringFormat属性。要全局设置日期格式,可以设置Thread.CurrentThread.CurrentCulture属性:

应用程序.xaml.cs

class App : Application
{
  protected override void OnStartup(StartupEventArgs e)
  {
    base.OnStartup(e);
    var globalCultureInfo = new CultureInfo("en-GB");

    /* Consider to set the CultureInfo.DefaultThread properties too */

    Thread.CurrentThread.CurrentCulture = globalCultureInfo;
    //Thread.CurrentThread.CurrentUICulture = globalCultureInfo;
  }
}

如果你不想改变线程文化,你可以使用一个以ContentControl为目标的隐式Style并将它定义在应用程序.xaml:

<Style TargetType="ContentControl">
  <Setter Property="ContentStringFormat"
          Value="dd.MM.yyyy" />
</Style>

TextBlockTextBox

对于文本元素,您必须设置或绑定 FrameworkElement.Language 属性,例如使用在中定义的隐式 Style应用程序.xaml全局应用语言:

<Style TargetType="ContentControl">
  <Setter Property="Language"
          Value="en-GB" />
</Style>

或者,您可以设置 Binding.StringFormat 属性或使用 IValueConverter。但如果您需要全局配置日期格式,这两种解决方案都无济于事。

FrameworkElementContentControlTextBlock 等)

要为所有 FrameworkElement 类型设置语言,您必须覆盖 FrameworkElement.Language 属性以覆盖默认值(即 "en-US"):

应用程序.xaml.cs

class App : Application
{
  protected override void OnStartup(StartupEventArgs e)
  {
    base.OnStartup(e);
    var globalCultureInfo = new CultureInfo("en-GB");

    /* Consider to set the Thread.CurrentThread 
       and CultureInfo.DefaultThread properties too */
   
    XmlLanguage defaultFrameworkLanguage = XmlLanguage.GetLanguage(cultureInfo.Name);
    FrameworkElement.LanguageProperty.OverrideMetadata(
      typeof(FrameworkElement),
      new FrameworkPropertyMetadata(defaultFrameworkLanguage)); 
  }
}

【讨论】:

    猜你喜欢
    • 2014-04-30
    • 1970-01-01
    • 1970-01-01
    • 2012-03-06
    • 2017-10-05
    • 1970-01-01
    • 1970-01-01
    • 2010-12-20
    • 1970-01-01
    相关资源
    最近更新 更多