Читайте также:
|
|
Построим пример разметки XAML, в котором привязка соединяет два свойства разных элементов управления.Для привязки данных определено расширения разметки {Binding}, что позволяет настроить привязку декларативно. Сделаем так, чтобы при перемещении ползунка слайдера автоматически менялся размер строки текста[12]:
<StackPanel>
<Slider Name="slider" Margin="3" Minimum="1" Maximum="40" />
<TextBlock Margin="10" Text="Sample Text" Name="lblText"
FontSize="{Binding ElementName=slider, Path=Value}"/>
</StackPanel>
Рис. 36. Привязка для элементов управления.
Привязку можно выполнить не только декларативно, но и используя код (а в некоторых ситуациях это единственный вариант). Нижеприведёнкодпрограммнойпривязки, эквивалентной примеру разметки XAML:
Binding binding = newBinding();
binding.Source = slider;
binding.Path = newPropertyPath("Value");
lblText.SetBinding(TextBlock.FontSizeProperty, binding);
Заданную привязку можно удалить в коде, используя два статических метода класса BindingOperations. Метод ClearBinding() принимает ссылку на свойство зависимостей, которое имеет привязку, подлежащую удалению, аClearAllBindings() удаляет все привязки элемента:
BindingOperations.ClearAllBindings(lblText);
Следующий пример XAMLдемонстрирует двунаправленную привязку: при перемещении ползунка слайдера меняется текст в TextBox, акорректное изменение текста (допустимы вещественные числа) ведёт к перемещению ползунка. Обратите внимание на установку UpdateSourceTrigger=PropertyChanged. Это обеспечивает мгновенные изменения позиции ползунка прямо при вводе текста.
<StackPanel>
<Slider Name="slider" Minimum="1" Maximum="40" Value="10" />
<TextBox Name="txtSize"
Text="{Binding ElementName=slider, Path=Value,
Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</StackPanel>
ЕслиUpdateSourceTriggerустановитьвUpdateSourceTrigger.Explicit, требуетсянаписатькод, вызывающийдляобновленияметодUpdateSource()уобъектаBindingExpression, связанногосэлементом:
// получить выражение привязки для текстового поля
BindingExpression binding =
txtSize.GetBindingExpression(TextBox.TextProperty);
// обновитьсвязанныйисточник (Slider)
binding.UpdateSource();
Рассмотрим сценарии, в которых источником привязки является не элемент WPF, а обычный объект. В этом случае вместо ElementName используется одно из описанных ниже свойств:
· Source – свойство привязки, указывающее на объект-источник.
· RelativeSource– свойство привязки, которое указывает на источник относительно текущего элемента. Это подход, часто применяемый при разработке шаблонов элементов управления и шаблонов данных.
· DataContext– наследуемое свойство FrameworkElement.Если источник не указан через Source или RelativeSource, WPF выполняет поиск по дереву элементов, начиная с текущего элемента. В качестве источника данных будет использоваться первый DataContext, не равный null.
Следующий пример разметки XAMLдемонстрирует использование свойства Source для связывания с объектом класса Person. Так как объект-источник должен существовать на момент выполнения привязки, этот объект помещается в словарь ресурсов окна.
<Window x:Class="WpfApplication.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication">
<Window.Resources>
<local:Person x:Key="person" Name="Mr. Smith" Age="27.3" />
</Window.Resources>
<StackPanel>
<TextBox Text="{Binding Source={StaticResource person},
Path=Name}"/>
</StackPanel>
</Window>
publicclassPerson
{
publicstring Name { get; set; }
publicdouble Age { get; set;}
publicstring Address { get; set; }
}
Модификация примера использует для размещения объекта привязки свойство DataContext у контейнера StackPanel:
<!--пропущена настройка окна и объявление ресурса[13]-->
<StackPanel DataContext="{StaticResource person}">
<TextBox Text="{BindingName}"/>
</StackPanel>
Свойство привязки RelativeSource позволяет указать объект-источник на основе его отношения к целевому объекту. Например, можно использовать RelativeSource для привязки элемента к самому себе или к родительскому элементу, находящемуся на неизвестное число шагов вверх по дереву элементов.Для установки свойства Binding.RelativeSourceиспользуется объект класса RelativeSource. При этом можно использовать как специальное расширение разметки, так и синтаксис, основанный на элементах-свойствах.
<!-- используем элемент-свойство XAML -->
<TextBlock>
<TextBlock.Text>
<Binding Path="Title">
<Binding.RelativeSource>
<RelativeSource Mode="FindAncestor"
AncestorType="{x:Type Window}" />
</Binding.RelativeSource>
</Binding>
</TextBlock.Text>
</TextBlock>
<!--используемрасширениеразметки -->
<TextBlock Text="{Binding Path=Title,
RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type Window}}}" />
В табл. 13 перечислены четыре возможных режима для RelativeSource.
Таблица 13
Значения перечисления RelativeSourceMode
Имя | Описание |
Self | Выражение привязывает к другому свойству того же элемента |
FindAncestor | Выражение привязывает к родительскому элементу. WPF будет производить поиск вверх по дереву элементов, пока не найдёт нужного родителя. Чтобы специфицировать родителя, необходимо также установить свойство AncestorType для указания типа родительского элемента. Можно использовать свойство AncestorLevel, чтобы пропустить определённое число вхождений указанного элемента |
PreviousData | Выражение привязывает к предыдущему элементу данных в списке |
TemplatedParent | Выражение привязывает к элементу, к которому применён шаблон. Этот режим работает, только если привязка расположена внутри шаблона элемента управления или шаблона данных |
Если при привязке к объекту.NETнеобходимо, чтобы привязка отслеживала изменения в объекте, можно поступить одним из следующих способов:
· Сделать отслеживаемые свойства объекта-источника свойствами зависимостей, а сам объект наследовать от DependencyObject.
· Инициировать при изменении свойства события ИмяСвойства Changed.
· Реализовать в объекте-источнике интерфейс INotifyPropertyChanged, содержащий событиеPropertyChanged. Это событие нужно инициировать всякий раз, когда свойство изменяется, передавая имя свойства.
Ниже приведена реализация класса Person, использующая третий подход:
publicclassPerson: INotifyPropertyChanged
{
publiceventPropertyChangedEventHandler PropertyChanged;
protectedvirtualvoid OnPropertyChanged(string propertyName)
{
if (PropertyChanged!= null)
PropertyChanged(this,
newPropertyChangedEventArgs(propertyName));
}
privatestring _name;
publicstring Name
{
get {return _name}
set{
if (value!= _name)
{
_name = value;
OnPropertyChanged("Name");
}
}
} // остальные свойства надо реализовать аналогично
}
Дата добавления: 2015-11-14; просмотров: 38 | Нарушение авторских прав
<== предыдущая страница | | | следующая страница ==> |
Базовые концепции привязки данных | | | Конвертеры значений |