четверг, 1 ноября 2012 г.

Binding к статическим полям статических классов

Давно хотел написать про это пример, но все как то руки не доходили, ну а тут на форуме MSDN-овском возник вопрос, где это может пригодится, поэтому сегодня напишу пример того, как можно выполнить Binding к статическому полю.
Итак, задача. Нужно выполнить Binding к полю, которое доступно как статическое, при этом необходимо, чтобы изменения поля в пользовательском интерфейсе отображалис
Основная проблема состоит в данном случае в том, что пользовательскому интерфейсу узнать, о том, что связанное через Binding свойство поменялось можно либо через интефейс INotifyPropertyChanged лиюо через наследование от DependencyObject. Я примеры этих способов приводил вот здесь.
Если же нам нужен всего один экземпляр строки со статусом, с которым будут работать все остальные классы программы, это действительно лучше всего сделать через статические классы, но для адекватной работы Binding необходимо реализовать наследование, а оно применимо только к динамическим классам... Решить это можно введением ститческого класса реализующего паттерн Singleton. В рассматриваемом случае реализация может иметь вид:

namespace WpfApplication19
{
    public class MyStatus : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        privateMyStatus() { }
        private string _status;
       public string Status
        {
            get
            {
                return _status;
            }
            internal set
            {
                if (_status != value)
                {
                    _status = value;
                    PropertyChangedEventHandler handler = PropertyChanged;
                    if (handler != null)
                    {
                        handler(this, new PropertyChangedEventArgs("Status"));
                    }
               }
            }
        }
       #region Статическая часть
        static MyStatus()
        {
       Inctance = new MyStatus();
        }
        public static MyStatus Inctance { get; private set; }
        #endregion
    }
}
Ок. Теперь, я на главной форме делаю вот такую верстку:
<Window x:Class="WpfApplication19.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication19"
        Title="MainWindow" Height="350" Width="525" >
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="30" />
            <RowDefinition Height="1*" />
           <RowDefinition Height="30" />
        </Grid.RowDefinitions>
       <Button Content="Поменять строку" Click="Button_Click"></Button>
        <StatusBar Grid.Row="2">
            <StatusBarItem>
                <TextBlock DataContext="{Binding Source={x:Static local:MyStatus.Inctance}}" Text="{Binding Path=Status}" />
            </StatusBarItem>
        </StatusBar>
</Grid>
</Window>
Обратите внимание, на подключение пространства имен:
xmlns:local="clr-namespace:WpfApplication19"
И на сам Binding к динамическому полю, статического поля, статического класса.
Ну и на кнопку я поместил вот такой демонстрационный код:
private void Button_Click(object sender, RoutedEventArgs e)
{
    string[] messages = { "первый", "второй", "третий" };
    Random rnd = new Random();
    MyStatus.Inctance.Status = messages[rnd.Next(3)];
}
При запуске приложения и кликах на кнопке, текст в статусбаре меняется:
Ну а так как, класс MyStatus статический, то поле Status мы сможем присваивать не только с главной формы, но и из любого другого места нашего приложения.

1 комментарий: