Во первых Binding это привязка данных, это просто и думаю все это прекрасно понимают и ни для кого это не станет откровением. Но не все понимают что с чем привязывается и зачем это надо, ну так давайте попробуем в этом разобраться. Первая и самая главная полезность которую мы получаем при использовании Binding'ов это разделение понятий отображения и логики, то есть грубо говоря мы имеем некую «морду» которую мы показываем пользователю и логику данных которая спрятана за этой «мордой». Так вот, начнем с простого примера, как все начинают .
Код окна:
<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 файл:
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» он уже связан с нашим окном, но все-же чтобы завершить привязку немного модифицируем наш код следующим образом.
<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 после модификации
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; } get { 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 предающее окну сообщение с именем поля класса данных в котором произошли изменения данных благодаря чему окно может обновить свое отображение. Так вот получается что не так уж много надо для успешного применения привязки данных, а именно: окно с элементами которые знают откуда и как брать данные и логика умеющая своевременно сообщить о том что данные изменились…
Продолжение следует…