На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: maxim84_
  
> Сага о WPF Binding часть первая , посвящено множеству возгласов на тему "Опять Binding, Уже нет сил...."
    На самом деле Binding очень хорошая и полезная штука, и ничего в нем сложного и особенного. В этой статье я попробую описать простой пример его использования или применения, называйте как хотите.


    Binding, что это такое и для чего он нужен.

    Во первых Binding это привязка данных, это просто и думаю все это прекрасно понимают и ни для кого это не станет откровением. Но не все понимают что с чем привязывается и зачем это надо, ну так давайте попробуем в этом разобраться. Первая и самая главная полезность которую мы получаем при использовании Binding'ов это разделение понятий отображения и логики, то есть грубо говоря мы имеем некую "морду" которую мы показываем пользователю и логику данных которая спрятана за этой "мордой". Так вот, начнем с простого примера, как все начинают :) .

    Код окна

    ExpandedWrap disabled
      <Window x:Class="WpfBinding.SampleBinding"
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
          Title="SampleBinding" Height="300" Width="300" Loaded="Window_Loaded">
          <Grid>
              <Grid.RowDefinitions>
                  <RowDefinition Height="Auto"/>
                  <RowDefinition Height="Auto"/>
                  <RowDefinition Height="Auto"/>
                  <RowDefinition Height="*"/>
                  <RowDefinition Height="Auto"/>
              </Grid.RowDefinitions>
              <TextBox Name="helloBox" Text="{Binding TextData}"/>
              <Button Name="helloBtn" Grid.Row="4" Width="100" Content="Hello" Click="helloBtn_Click" HorizontalAlignment="Right"/>
          </Grid>
      </Window>


    и соответственно код нашей логики данных, то биш SampleBinding.cs файл

    ExpandedWrap disabled
      using System.Windows;
       
      namespace WpfBinding
      {
          /// <summary>
          /// Interaction logic for SampleBinding.xaml
          /// </summary>
          public partial class SampleBinding
          {
              public SampleBinding()
              {
                  InitializeComponent();
              }
       
              public string TextData { get; set; }
       
              private void helloBtn_Click(object sender, RoutedEventArgs e)
              {
                  TextData = "Hello";
              }
       
              private void Window_Loaded(object sender, RoutedEventArgs e)
              {
                  TextData = "Click Hello button";
              }
          }
      }


    что нам надо, при старте программы загрузить в helloBox строку "Click Hello button" а по нажатию кнопки поменять текст на "Hello", вроде бы все просто, но после запуска программы мы видим что ничего не работает. Почему скажите вы, ведь у нас есть строка Text="{Binding TextData}" которая должна была обеспечить нам привязку, а потому что просто привязка ничего не значит, ведь мы не указали окну откуда брать данные, привязка есть но с чем не сказано. Мы должны дать нашему окну DataContext к данным которого мы будем привязывать поля нашей формы. DataContext у нас есть, и даже более того судя по строчке Window x:Class="WpfBinding.SampleBinding" он уже связан с нашим окном, но все-же чтобы завершить привязку немного модифицируем наш код следующим образом.

    ExpandedWrap disabled
      <Window x:Class="WpfBinding.SampleBinding"
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
          Title="SampleBinding" Height="300" Width="300" Loaded="Window_Loaded" Name="sampleWindow">
          <Grid>
              <Grid.RowDefinitions>
                  <RowDefinition Height="Auto"/>
                  <RowDefinition Height="Auto"/>
                  <RowDefinition Height="Auto"/>
                  <RowDefinition Height="*"/>
                  <RowDefinition Height="Auto"/>
              </Grid.RowDefinitions>
              <TextBox Name="helloBox" Text="{Binding ElementName=sampleWindow, Path=TextData}"/>
              <Button Name="helloBtn" Grid.Row="4" Width="100" Content="Hello" Click="helloBtn_Click" HorizontalAlignment="Right"/>
          </Grid>
      </Window>


    Рассмотрим что изменилось в коде окна. А изменилось то что мы дали имя sampleWindow классу нашего окна и сказали текстовому полю что брать данные надо из элемента с именем sampleWindow по пути TextData, по сути задав ему этим самым DataContext. Но и этого пока не достаточно потому как при инициализации окна когда после создания элементов инициализируются привязки в TextData не заданно значение и мы привязываемся к пустому полю. Так как же быть, как сообщить окну, или даже не окну, а текстовому полю что данные в нашем классе логики изменились. Для этого нам понадобиться тот волшебный интерфейс про который я не раз вспоминал отвечая на вопросы по привязке данных в топиках нашего форума и который так никто и не хочет видеть в упор, речь идет о INotifyPropertyChanged из System.ComponentModel. Что он нам дает, а дает он нам единственное событие которое посылает окну PropertyChangedEventArgs извещая о том что поменялось поле обнови данные. И вот как будет выглядеть код SampleBinding.cs после модификации

    ExpandedWrap disabled
      using System.ComponentModel;
      using System.Windows;
       
      namespace WpfBinding
      {
          /// <summary>
          /// Interaction logic for SampleBinding.xaml
          /// </summary>
          public partial class SampleBinding : INotifyPropertyChanged
          {
              public SampleBinding()
              {
                  InitializeComponent();
              }
       
              private string textData;
              public string TextData
              {
                  get { return textData; }
                  set
                  {
                      textData = value;
                      OnPropertyChanged("TextData");
                  }
              }
       
              private void helloBtn_Click(object sender, RoutedEventArgs e)
              {
                  TextData = "Hello";
              }
       
              private void Window_Loaded(object sender, RoutedEventArgs e)
              {
                  TextData = "Click Hello button";
              }
       
              #region Implementation of INotifyPropertyChanged
       
              public event PropertyChangedEventHandler PropertyChanged;
              public void OnPropertyChanged(string propertyName)
              {
                  if (PropertyChanged != null)
                      PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
              }
              #endregion
          }
      }


    Рассмотрим что что мы имеем. В результате реализации INotifyPropertyChanged как я говорил раньше мы получаем событие public event PropertyChangedEventHandler PropertyChanged предающее окну сообщение с именем поля класса данных в котором произошли изменения данных благодаря чему окно может обновить свое отображение. Так вот получается что не так уж много надо для успешного применения привязки данных, а именно: окно с элементами которые знают откуда и как брать данные и логика умеющая своевременно сообщить о том что данные изменились...

    Продолжение следует ................
      Просто огроменное спасибо! Перерыл 2 толстнные книги и гугл, потратил 2 дня, прочитал Ваш пост и наконец то понял, в чем была засада.
      Спасибо !
      0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
      0 пользователей:


      Рейтинг@Mail.ru
      [ Script execution time: 0,0198 ]   [ 16 queries used ]   [ Generated: 19.04.24, 05:11 GMT ]