Silverlight XAML TextBlock 中的当前日期

发布于 2024-08-24 11:29:45 字数 295 浏览 7 评论 0原文

我来自 Flex,在那里你可以在花括号内做任何事情。我试图让 TextBlock 来显示今天的日期和时间,而无需仅用 C# 进行编码。我尝试了以下许多不同的变体,但没有成功。

TextBlock Text="{Source=Date, Path=Now, StringFormat='dd/MM/yyyy'}"

我知道我可能只需设置一个属性 MyDate 并绑定到该属性,但为什么我不能直接绑定到 DateTime.Now 属性?

I am coming from Flex where you can do just about anything inside of curly braces. I am trying to get a TextBlock to display today's Date and Time without just coding it in C#. I have tried many different variations of the following with no luck.

TextBlock Text="{Source=Date, Path=Now, StringFormat='dd/MM/yyyy'}"

I know I could probably just set a property MyDate and bind to that but why can't I bind directly to the DateTime.Now property?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

删除会话 2024-08-31 11:29:46

Silverlight 中的绑定需要 Source 对象或 Dependency 对象。从该源对象,您可以绑定到属性(因此根据定义,您将绑定到实例成员)或依赖项属性。

由于 DateTime.Now 是一个静态属性,您无法在 Silverlight 中直接绑定到它,因此需要一些代码。下一个最好的事情是使用代码来: -

  • 确保您需要的尽可能多的内容可以在 XAML 中表达,
  • 从而以尽可能解耦的方式实现。

因此我们可以分析我们需要两件事。

  1. 将 DateTime 的静态成员公开为某个对象的实例属性
  2. 有某种方法将 DateTime 格式化为所需的输出。

为了处理第一个项目,我将创建一个 StaticSurrogate 类,在其中为我们需要访问的静态属性创建实例属性:-

public class StaticSurrogate
{
    public DateTime Today { get { return DateTime.Today; } }
    public DateTime Now { get { return DateTime.Now; } }
}

现在我们需要一种方法来格式化日期时间。值转换器是完成这项工作的正确工具,它大量借鉴了这个Tim Heuer 博客:-

public class FormatConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (parameter != null)
        {
            string formatterString = parameter.ToString();

            if (!String.IsNullOrEmpty(formatterString))
            {
                return String.Format(culture, String.Format("{{0:{0}}}", formatterString), value);
            }
        }

        return (value ?? "").ToString();
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

有了这两个类,我们现在可以在 Xaml 中完成剩下的工作,首先我们需要在资源中使用这些类的实例:-

<UserControl.Resources>
    <local:StaticSurrogate x:Key="Static" />
    <local:FormatConverter x:Key="Formatter" />     
</UserControl.Resources>

现在我们可以连接TextBlock :-

<TextBlock Text="{Binding Today, Source={StaticResource Static},
    Converter={StaticResource Formatter}, ConverterParameter='dd MMM yyy'}" />

请注意,这种方法具有以下优点:-

  • 我们不需要向放置 TextBlock 的 UserControl 添加代码,也不需要摆弄任何数据上下文。
  • 静态资源可以放置在 App.Resources 中,这将使 TextBlock 的创建完全独立于向 UserControl 添加任何其他内容。
  • 用于显示日期的格式可以单独修改。
  • 可以轻松地将对其他静态属性的访问添加到StaticSurrogate 类中。

Binding in Silverlight requires a Source object or a Dependency object. From that source object you can bind to Properties (hence by definition you are binding to instance members) or Dependency Properties.

Since DateTime.Now is a static property you cannot bind to it in Silverlight directly, hence some code is needed. The next best thing is to use code to:-

  • ensure as much of what you need can be expressed in XAML
  • to do so in an as de-coupled manner as possible.

Hence we can analyse that we need two things.

  1. Expose the static members of DateTime as instance properties of some object
  2. Have some way to format the DateTime to a desirable output.

To handle the first item I would create a StaticSurrogate class, where I would create instance properties for the static properties that we need access to:-

public class StaticSurrogate
{
    public DateTime Today { get { return DateTime.Today; } }
    public DateTime Now { get { return DateTime.Now; } }
}

Now we need a way to format a Date time. A value converter is the right tool for this job, borrowing heavily from this Tim Heuer Blog :-

public class FormatConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (parameter != null)
        {
            string formatterString = parameter.ToString();

            if (!String.IsNullOrEmpty(formatterString))
            {
                return String.Format(culture, String.Format("{{0:{0}}}", formatterString), value);
            }
        }

        return (value ?? "").ToString();
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

With these two classes in place we can now do the rest in Xaml, first we need instances of these classes in our resources:-

<UserControl.Resources>
    <local:StaticSurrogate x:Key="Static" />
    <local:FormatConverter x:Key="Formatter" />     
</UserControl.Resources>

Now we can wire up the TextBlock :-

<TextBlock Text="{Binding Today, Source={StaticResource Static},
    Converter={StaticResource Formatter}, ConverterParameter='dd MMM yyy'}" />

Note that this approach has the following advantages:-

  • we do not need to add code to the UserControl on which the TextBlock is placed, nor do we have to fiddle around with any data context.
  • The Static resources could be placed in the App.Resources which would make the creation of the TextBlock entirely independent of having to add anything else to the UserControl.
  • The formatting used to display the date can be independently modified.
  • Access to additional static properties can easily be added to the StaticSurrogate class.
2024-08-31 11:29:46

即使您可以在 Silverlight 的 XAML 中声明 DateTime.Now (因为您可以在 WPF 中 - http://soumya.wordpress.com/2010/02/12/wpf-simplified-part-11-xaml-tricks/),您遇到的问题是您的时间不会更新。如果您使用每秒更新的本地计时器,您可以确保您的时间也会更新。

public class LocalTimer : INotifyPropertyChanged
{
    private DispatcherTimer timer;

    public LocalTimer()
    {
        timer = new DispatcherTimer();
        timer.Interval = TimeSpan.FromSeconds(1.0);
        timer.Tick += new EventHandler(TimerCallback);
        this.TimeFormat = "hh:mm:ss";
        this.DateFormat = "dddd, MMMM dd";
    }

    private void TimerCallback(object sender, EventArgs e)
    {
        PropertyChanged(this, new PropertyChangedEventArgs("FormattedDate"));
        PropertyChanged(this, new PropertyChangedEventArgs("FormattedTime"));
    }

    public bool Enabled
    {
        get { return this.timer.IsEnabled; }
        set { if (value) this.timer.Start(); else this.timer.Stop(); }
    }

    public string FormattedDate { get { return DateTime.Now.ToString(this.DateFormat); } set {} }
    public string FormattedTime { get { return DateTime.Now.ToString(this.TimeFormat); } set{} }

    public string TimeFormat { get; set; }
    public string DateFormat { get; set; }

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    #endregion
}

在 xaml ala: 中声明此实例,

<local:LocalTimer x:Key="theTime" Enabled="True" />

并使用绑定来确保始终反映您的时间。

<TextBlock Text="{Binding Source={StaticResource theTime}, Path=FormattedDate, Mode=OneWay}" x:Name="TodaysDate" />
<TextBlock Text="{Binding Source={StaticResource theTime}, Path=FormattedTime, Mode=OneWay}" x:Name="CurrentTime" />

Even if you could declare DateTime.Now in Silverlight's XAML (since you can in WPF - http://soumya.wordpress.com/2010/02/12/wpf-simplified-part-11-xaml-tricks/), you have the issue that your time won't update. If you use a local timer that updates on the second you can ensure that your time will update as well.

public class LocalTimer : INotifyPropertyChanged
{
    private DispatcherTimer timer;

    public LocalTimer()
    {
        timer = new DispatcherTimer();
        timer.Interval = TimeSpan.FromSeconds(1.0);
        timer.Tick += new EventHandler(TimerCallback);
        this.TimeFormat = "hh:mm:ss";
        this.DateFormat = "dddd, MMMM dd";
    }

    private void TimerCallback(object sender, EventArgs e)
    {
        PropertyChanged(this, new PropertyChangedEventArgs("FormattedDate"));
        PropertyChanged(this, new PropertyChangedEventArgs("FormattedTime"));
    }

    public bool Enabled
    {
        get { return this.timer.IsEnabled; }
        set { if (value) this.timer.Start(); else this.timer.Stop(); }
    }

    public string FormattedDate { get { return DateTime.Now.ToString(this.DateFormat); } set {} }
    public string FormattedTime { get { return DateTime.Now.ToString(this.TimeFormat); } set{} }

    public string TimeFormat { get; set; }
    public string DateFormat { get; set; }

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    #endregion
}

Declare an instance of this in xaml ala:

<local:LocalTimer x:Key="theTime" Enabled="True" />

and use the binding to ensure that your time is always reflected.

<TextBlock Text="{Binding Source={StaticResource theTime}, Path=FormattedDate, Mode=OneWay}" x:Name="TodaysDate" />
<TextBlock Text="{Binding Source={StaticResource theTime}, Path=FormattedTime, Mode=OneWay}" x:Name="CurrentTime" />
别在捏我脸啦 2024-08-31 11:29:46
xmlns:sys="clr-namespace:System;assembly=mscorlib"

Text="{Binding Source={x:Static sys:DateTime.Today}, StringFormat='Today is {0:dddd, MMMM dd}'}"
xmlns:sys="clr-namespace:System;assembly=mscorlib"

Text="{Binding Source={x:Static sys:DateTime.Today}, StringFormat='Today is {0:dddd, MMMM dd}'}"
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文