Текущая дата в Silverlight XAML TextBlock - PullRequest
8 голосов
/ 12 марта 2010

Я из Флекса, где вы можете делать что угодно внутри фигурных скобок. Я пытаюсь получить TextBlock для отображения сегодняшней даты и времени, не кодируя их только в C #. Я попробовал много различных вариантов следующего без удачи.

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

Я знаю, что, возможно, я мог бы просто установить свойство MyDate и связать его, но почему я не могу связать напрямую со свойством DateTime.Now?

Ответы [ 3 ]

14 голосов
/ 12 марта 2010

Для привязки в Silverlight требуется объект-источник или объект зависимости. Из этого исходного объекта вы можете связать со свойствами (следовательно, по определению вы связываетесь с членами экземпляра) или со свойствами зависимости.

Так как 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'}" />

Обратите внимание, что этот подход имеет следующие преимущества: -

  • нам не нужно добавлять код в UserControl, в который помещается TextBlock, и при этом нам не нужно возиться с каким-либо контекстом данных.
  • Статические ресурсы могут быть размещены в App.Resources, что сделает создание TextBlock полностью независимым от необходимости добавлять что-либо еще в UserControl.
  • Форматирование, используемое для отображения даты, может быть изменено независимо.
  • Доступ к дополнительным статическим свойствам можно легко добавить к классу StaticSurrogate.
7 голосов
/ 12 марта 2010

Даже если вы можете объявить DateTime.Now в XAML Silverlight (поскольку вы можете в 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" />
1 голос
/ 09 марта 2011
xmlns:sys="clr-namespace:System;assembly=mscorlib"

Text="{Binding Source={x:Static sys:DateTime.Today}, StringFormat='Today is {0:dddd, MMMM dd}'}"
...