英文:
How can I bind a long value and display it as a formatted date in XAML?
问题
在MonkeyViewModel
中,我有一个名为DateTime TimestampToDatetime(long Timestamp)
的方法,它返回一个DateTime
对象。
在Monkey
模型中,我有一个名为long DateModified
的时间戳变量。
在XAML中,我想要将这个时间戳显示为一个日期时间字符串,例如,将长整数时间戳1685299649000
显示为字符串日期时间2023年5月28日
。
我应该如何像这样做:TimestampToDatetime(DateModified).ToString()
?
换句话说,是否可能将两个属性绑定到同一个标签中,而且在同一个绑定属性中将一个属性传递给另一个属性作为参数?
是否有类似以下语法的方式:
<Label Text="{Binding TimestampToDatetime(DateModified).ToString(), x:Type ViewModel:MonkeyViewModel}" />
英文:
I have a method DateTime TimestampToDatetime(long Timestamp) (return new DateTime(Timestamp))
defined in MonkeyViewModel
,
and a variable long DateModified
which is a timestamp defined in Monkey
Model.
In the XAML, I want the timestamp display as a datetime string, for example, the long DateModified 1685299649000
display as a string datetime May 28, 2023
How can I do something like TimestampToDatetime(DateModified).toString()
?
In other words, is it possible to bind two properties into same tag and inside the same binding attribute and pass one of the properties to another as a parameter?
Is there any similar syntax like the following:
<Label Text="{
Binding TimestampToDatetime, x:Type ViewModel: MonkeyViewModel
({
Binding DateModified, x:Type model:Mondey
}).tostring()
}">
答案1
得分: 2
备注:通常建议将日期存储为DateTime
对象,而不是其他数据类型。您应该使用已经存在的内容。
如果您无法或不想更改变量类型,那么您至少需要将其转换为属性。如果该值可能会更改,需要通过手动实现INotifyPropertyChanged接口或使用MVVM Community Toolkit的Source Generators来使其可观察:
[ObservableProperty]
private long dateModified;
这将为您自动生成一个名为DateModified
的public
属性(注意符号名称的小写和大写字母之间的区别),在底层看起来类似于这样:
private long dateModified;
public long DateModified
{
get => dateModified;
set
{
if(dateModified.Equals(value)) return;
dateModified = value;
OnPropertyChanged();
}
}
您可以在我的博客上找到关于Source Generators的更多信息。
然后,您可以实现一个value converter,将long
转换为DateTime
,例如:
public class LongToDateTimeConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if(value is long ticks)
{
return new DateTime(ticks);
}
// 回退值,也可以是其他值
return DateTime.MinValue;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return Binding.DoNothing;
}
}
**注意:**您可能需要根据自己的需求修改转换器代码。我假设long值存储的是ticks。如果它存储毫秒或其他内容,您需要使用适当的转换方法。
然后,您可以在XAML中使用此转换器将DateModified
属性转换为DateTime
对象,然后在绑定表达式中指定字符串格式:
<ContentPage.Resources>
<ResourceDictionary>
<converters:LongToDateTimeConverter x:Key="LongToDateConverter" />
</ResourceDictionary>
</ContentPage.Resources>
<VerticalStackLayout>
<Label
Text="{Binding DateModified, Converter={StaticResource LongToDateConverter}, StringFormat='{0:M}, {0:yyyy}'}"/>
</VerticalStackLayout>
您可能需要尝试不同的string format,直到满足您的需求。有一个广泛的标准日期和时间格式列表。如果我没有记错,StringFormat='{0:M}, {0:yyyy}'
应该生成类似于 May 28, 2023
的内容。
还有其他几种方法可以实现这一点,例如,您还可以将属性转换为string
属性并绑定到该属性,或者更改转换器以直接生成格式化的string
。然而,我建议使用上述解决方案,因为它在字符串格式方面提供了更多的灵活性。在XAML中更容易更改,并且甚至可以根据区域设置提供不同的格式,以及在绑定到同一属性时使用不同的格式来为不同的标签使用不同的格式。
英文:
Remark: Generally, it's recommended to store dates as DateTime
objects and not as other data types. You should use what's already there.
If you cannot or do not want to change your variable type, then you need to at least turn it into a property. If the value is subject to change, it needs to be made observable by either manually implementing the INotifyPropertyChanged interface or by using the MVVM Community Toolkit's Source Generators:
[ObservableProperty]
private long dateModified;
This will auto-generate a public
property with the name DateModified
for you (mind the difference of the lower case and upper case letters of the symbol names) looking similar to this under the hood:
private long dateModified;
public long DateModified
{
get => dateModified;
set
{
if(dateModified.Equals(value) return;
dateModified = value;
OnPropertyChanged();
}
}
You can find more information about Source Generators on my blog.
Then, you can implement a value converter that converts a long
to a DateTime
, e.g.:
public class LongToDateTimeConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if(value is long ticks)
{
return new DateTime(ticks);
}
// Fallback value, could also be something else
return DateTime.MinValue;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return Binding.DoNothing;
}
}
Note: You may need to modify the converter code according to your needs. I've assumed that the long value stores ticks. If it stores milliseconds or anything else, you need to use an appropriate conversion method.
You can then use this converter in your XAML to convert the DateModified
property to a DateTime
object and then specify a string format in the binding expression:
<ContentPage.Resources>
<ResourceDictionary>
<converters:LongToDateTimeConverter x:Key="LongToDateConverter" />
</ResourceDictionary>
</ContentPage.Resources>
<VerticalStackLayout>
<Label
Text="{Binding DateModified, Converter={StaticResource LongToDateConverter}, StringFormat='{0:M}, {0:yyyy}'}"/>
</VerticalStackLayout>
You may need to experiment with the string format until you have what you need. There's an extensive list of standard date and time formats. If I'm not mistaken, StringFormat='{0:M}, {0:yyyy}'}
should produce something like May 28, 2023
.
There are several other ways to do this, e.g. you could also convert the property to a string
property and bind to that or change the converter to produce a formatted string
already. I suggest to use the above solution, however, because it provides more flexibility regarding the string format. It's easier to change in the XAML and you could even provide different formats per locale and you can use different formats for separate labels while binding to the same property.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论