如何将长整型值绑定并在XAML中以格式化日期的方式显示?

huangapple go评论75阅读模式
英文:

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:

&lt;Label Text=&quot;{
Binding TimestampToDatetime, x:Type ViewModel: MonkeyViewModel
    ({
        Binding DateModified, x:Type model:Mondey
    }).tostring()
}&quot;&gt;

答案1

得分: 2

备注:通常建议将日期存储为DateTime对象,而不是其他数据类型。您应该使用已经存在的内容。

如果您无法或不想更改变量类型,那么您至少需要将其转换为属性。如果该值可能会更改,需要通过手动实现INotifyPropertyChanged接口或使用MVVM Community Toolkit的Source Generators来使其可观察:

[ObservableProperty]
private long dateModified;

这将为您自动生成一个名为DateModifiedpublic属性(注意符号名称的小写和大写字母之间的区别),在底层看起来类似于这样:

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 =&gt; 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:

&lt;ContentPage.Resources&gt;
    &lt;ResourceDictionary&gt;
        &lt;converters:LongToDateTimeConverter x:Key=&quot;LongToDateConverter&quot; /&gt;
    &lt;/ResourceDictionary&gt;
&lt;/ContentPage.Resources&gt;

&lt;VerticalStackLayout&gt;
    &lt;Label
        Text=&quot;{Binding DateModified, Converter={StaticResource LongToDateConverter}, StringFormat=&#39;{0:M}, {0:yyyy}&#39;}&quot;/&gt;
&lt;/VerticalStackLayout&gt;

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=&#39;{0:M}, {0:yyyy}&#39;} 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.

huangapple
  • 本文由 发表于 2023年5月29日 02:55:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/76353130.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定