Reputation: 129
I develop some application. And I've found some strange things related to the DateTime format. So I've created some test application to check it in more detail. So, my test application has the next structure:
Custom object class with only Date property:
public class MyObject
{
public DateTime Date { get; private set; }
public MyObject(DateTime date)
{
Date = date;
}
}
Custom ViewModel class:
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));
}
}
View control with DataGrid and ListView. Both of them have a binding to the same TableView collection:
<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>
In this case I see a different view of the date in the table and in the list:
In case when I change the Label to the TextBlock in the ListView item template I will see the same result:
Why did it happen? And how can I display the same format in all controls according to the Culture date-time settings?
Upvotes: 0
Views: 305
Reputation: 29028
While ContentControl
(and therefore Label
too) uses the ContentControl.ContentStringFormat
property to format string
content, the text elements like TextBlock
or TextBox
use the FrameworkElement.Language
property, which defaults to "en-US"
.
ContentControl
(and Label
)In case of the ContentControl
, where ContentControl.ContentStringFormat
is not explicitly defined, the string
is formatted using the Thread.CurrentThread.CurrentCulture
as fallback CultureInfo
(using the DateTimeFormatInfo
returned from the CultureInfo.DateTimeFormat
property).
In your case this is obviously not the language "en-US".
If you want to enforce a common date format on particular ContentControl
elements, you can use a named Style
to set ContentControl.ContentStringFormat
property. To set the date format globally , you can set the Thread.CurrentThread.CurrentCulture
property:
App.xaml.cs
class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
var globalCultureInfo = CultureInfo.GetCultureInfo("en-GB");
/* Consider to set the CultureInfo.DefaultThread properties too */
Thread.CurrentThread.CurrentCulture = globalCultureInfo;
//Thread.CurrentThread.CurrentUICulture = globalCultureInfo;
}
}
If you don't want to change the thread culture, you can use an implicit Style
that targets ContentControl
and define it in App.xaml:
<Style TargetType="ContentControl">
<Setter Property="ContentStringFormat"
Value="dd.MM.yyyy" />
</Style>
<Style TargetType="Label"
BasedOn="{StaticResource {x:Type ContentControl}}" />
TextBlock
and TextBox
For text elements you have to set or bind the FrameworkElement.Language
property, for example using an implicit Style
defined in App.xaml to apply the language globally:
<Style TargetType="ContentControl">
<Setter Property="Language"
Value="en-GB" />
</Style>
Alternatively, you can set the Binding.StringFormat
property or use a IValueConverter
. But both solutions are not helpful if you need to configure the date format globally.
FrameworkElement
(ContentControl
and TextBlock
etc.)To set the language for all FrameworkElement
types, you must override the FrameworkElement.Language
property in order to override the default value (which is "en-US"
):
App.xaml.cs
class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
var globalCultureInfo = CultureInfo.GetCultureInfo("en-GB");
/* Consider to set the Thread.CurrentThread
and CultureInfo.DefaultThread properties too */
XmlLanguage defaultFrameworkLanguage = XmlLanguage.GetLanguage(globalCultureInfo.Name);
FrameworkElement.LanguageProperty.OverrideMetadata(
typeof(FrameworkElement),
new FrameworkPropertyMetadata(defaultFrameworkLanguage));
}
}
Upvotes: 2