Главная » C#, Windows Runtime, XAML, Разработка для Windows 8 » Привязка к объекту Windows Runtime

0

На  практике  значительно  чаще  приходится  выполнять привязку  элементов к данным, которые содержатся в  объекте некоторого класса. Эти данные могут быть получены из базы данных или сгенерированы во время работы приложения.

Создадим простой класс, описывающий информацию о сотруднике:

public class Employee

{

public string FirstName

{

get; set;

}

public string LastName

{

get; set;

}

public string EMail

{

get; set;

}

public int Age

{

get; set;

}

}

Этот  класс  содержит  4  свойства с  модификатором  public.  Это   основное требование при привязке к  данным: свойства  объектов,  которые выступают в качестве источника, должны быть общедоступными.

Следующий код создает простую форму и связывает эту форму с объектом типа Employee, который мы определили в  ресурсах (аналогично можно определить и в коде):

<Page x:Class=" Chapter5_Binding.MainPage " xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="using:Element_Binding_Sample">

<Page.Resources>

<local:Employee x:Key="employee" Age="27" FirstName="Sergii" LastName="Lutai" EMail="sergii.lutai@dct.ua" />

</Page.Resources>

<Grid x:Name="LayoutRoot" Width="400">

<Grid.RowDefinitions>

<RowDefinition></RowDefinition>

<RowDefinition></RowDefinition>

<RowDefinition></RowDefinition>

<RowDefinition></RowDefinition>

</Grid.RowDefinitions>

<Grid.ColumnDefinitions>

<ColumnDefinition></ColumnDefinition>

<ColumnDefinition></ColumnDefinition>

</Grid.ColumnDefinitions>

<TextBlock Text="First Name:" Grid.Row="0" Grid.Column="0">

</TextBlock>

<TextBox Text="{Binding FirstName, Source={StaticResource employee}, Mode=TwoWay}"

Grid.Row="0" Grid.Column="1">

</TextBox>

<TextBlock Text="Last Name:" Grid.Row="1" Grid.Column="0">

</TextBlock>

<TextBox Text="{Binding LastName, Source={StaticResource employee}, Mode=TwoWay}"

Grid.Row="1" Grid.Column="1">

</TextBox>

<TextBlock Text="EMail:" Grid.Row="2" Grid.Column="0">

</TextBlock>

<TextBox Text="{Binding EMail, Source={StaticResource employee}, Mode=TwoWay}"

Grid.Row="2" Grid.Column="1">

</TextBox>

<TextBlock Text="Age:" Grid.Row="3" Grid.Column="0">

</TextBlock>

<TextBox Text="{Binding Age, Source={StaticResource employee}, Mode=TwoWay}"

Grid.Row="3" Grid.Column="1">

</TextBox>

</Grid>

</Page>

Как видите, механизм точно такой, как  и при привязке к элементам.  Только вместо ElementName используется свойство Source, которое задает ссылку на объект (в данном случае выбираемый из ресурсов).

Модифицируем код выше, используя еще одно полезное свойство — DataContext:

<Page x:Class="Chapter5_Binding.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="using:Element_Binding_Sample">

<Page.Resources>

<local:Employee x:Key="employee" Age="27" FirstName="Sergii" LastName="Lutai" EMail="sergii.lutai@dct.ua" />

</Page.Resources>

<Grid x:Name="LayoutRoot" Width="400" DataContext="{StaticResource employee}">

<Grid.RowDefinitions>

<RowDefinition></RowDefinition>

<RowDefinition></RowDefinition>

<RowDefinition></RowDefinition>

<RowDefinition></RowDefinition>

</Grid.RowDefinitions>

<Grid.ColumnDefinitions>

<ColumnDefinition></ColumnDefinition>

<ColumnDefinition></ColumnDefinition>

</Grid.ColumnDefinitions>

<TextBlock Text="First Name:" Grid.Row="0" Grid.Column="0">

</TextBlock>

<TextBox Text="{Binding FirstName, Mode=TwoWay}" Grid.Row="0" Grid.Column="1">

</TextBox>

<TextBlock Text="Last Name:" Grid.Row="1" Grid.Column="0">

</TextBlock>

<TextBox Text="{Binding LastName, Mode=TwoWay}" Grid.Row="1" Grid.Column="1">

</TextBox>

<TextBlock Text="EMail:" Grid.Row="2" Grid.Column="0">

</TextBlock>

<TextBox Text="{Binding EMail, Mode=TwoWay}" Grid.Row="2" Grid.Column="1">

</TextBox>

<TextBlock Text="Age:" Grid.Row="3" Grid.Column="0">

</TextBlock>

<TextBox Text="{Binding Age, Mode=TwoWay}" Grid.Row="3" Grid.Column="1">

</TextBox>

</Grid>

</Page>

Как Вы видите, нам немного удалось упростить код. Дело в том, что если не указать имя объекта с данными явно, то механизм привязки начинает перебор свойств DataContext всех родительских элементов, пока не найдет непустой. Найденный DataContext механизм связывания и используется в качестве источника.

Замечание. Если Вы будете использовать DataContext в коде, то класс Employee должен быть только public. При использовании через ресурсы можно обойтись и без public.

Итак, с первого взгляда, наш код работает правильно и вполне прогнозируемо. Но, если Вы попробуете изменить хотя бы одно свойство объекта типа Employee в  коде, то обнаружите, что значение в соответствующем поле не поменялось. Так, уберите DataContext из XAML кода, а вместо него реализуйте обработчик события Loaded:

protected override void OnNavigatedTo(NavigationEventArgs e)

{

Employee emp = new Employee(); emp.FirstName = "Sergii"; emp.LastName = "Lutai";

emp.EMail = "sergii.lutai@dct.ua"; emp.Age = 27;

LayoutRoot.DataContext = emp;

emp.FirstName = "Alex";

}

Тут  мы  создаем  объект  типа  Employee,  связываем  его  с  формой,  а  затем изменяем одно из свойств. Если запустить это пример, то можно обнаружить, что изменения не попали в форму. Это связано с тем, что у механизма привязки нет возможности  проверять значения  свойства объекта с данными. При этом для элементов управления механизм работал нормально, так как базировался на понятии зависимых свойств.

Если   мы   хотим   видеть  ожидаемое   поведение, необходимо   реализовать специальный     интерфейс     INotifyPropertyChanged.      Реализация      этого интерфейса  позволит механизму  привязки  данных  реагировать на  событие, связанное с изменением всех свойств. Правда инициировать  событие придется самостоятельно.  Вот   как   будет   выглядеть  класс   Employee,   реализующий INotifyPropertyChanged:

public class Employee: INotifyPropertyChanged

{

public event PropertyChangedEventHandler PropertyChanged;

public void OnPropertyChanged(PropertyChangedEventArgs e)

{

if (PropertyChanged != null) PropertyChanged(this, e);

}

private string firstName; private string lastName; private int age;

private string email;

public string FirstName

{

get { return firstName; } set

{

firstName = value;

OnPropertyChanged(new PropertyChangedEventArgs("FirstName"));

}

}

public string LastName

{

get { return lastName; } set

{

lastName = value;

OnPropertyChanged(new PropertyChangedEventArgs("LastName"));

}

}

public string EMail

{

get { return email; } set

{

email = value;

OnPropertyChanged(new PropertyChangedEventArgs("EMail"));

}

}

public int Age

{

get { return age; } set

{

age = value;

OnPropertyChanged(new PropertyChangedEventArgs("Age"));

}

}

}

Вот теперь приложение будет работать так, как и ожидалось.

Сергей Лутай, Сергей Байдачный, Windows 8 для C# разработчиков

По теме:

  • Комментарии