Опубликован: 05.08.2010 | Доступ: свободный | Студентов: 2008 / 45 | Оценка: 4.50 / 4.40 | Длительность: 60:26:00
Лекция 1:

Основы привязки данных в WPF

Часть II

Упражнение 2. Привязка интерфейсных элементов к невизуальным объектам

В предыдущем упражнении мы рассматривали привязку элементов, являющихся визуальными элементами WPF. Но такая задача, на самом деле, возникает редко. В реальных приложениях, предназначенных для управления данными и управляемых данными, чаще используются привязки, предназначенные для извлечения информации визуальными элементами из невизуальных объектов - хранителей и источников данных.

Прежде, чем начать рассмотрение таких привязок, стоит вернуться к классу Binding и познакомиться с ним более подробно. Этот класс обеспечивает возможность связывания данных, устанавливая связь конечного свойства: с исходным свойством элемента, с другим объектом или списком объектов-источников. Основные свойства класса Binding приведены в таблице, а терминология используется с учетом размещения выражения привязки на приемнике информации.

Основные свойства класса Binding
Свойство Тип Описание
ElementName String -класс Задает или извлекает имя элемента, который будет использоваться как источник информации. При связывании с элементом WPF применяется вместо свойства Source
FallbackValue Object -класс Задает или извлекает значение для использования, если привязка не может вернуть значение. Значение по умолчанию UnsetValue
Mode BindingMode -перечисление Получает или устанавливает значение, которое указывает направление потока данных в привязке
NotifyOnSourceUpdated Boolean -структура Получает или устанавливает флаг, который указывает, возбуждается ли событие SourceUpdated при передаче данных от целевого элемента к источнику
Path PropertyPath -класс Задает или извлекает путь к свойству источника
RelativeSource RelativeSource -класс Задает или извлекает источник путем указания его местоположения относительно целевого элемента в визуальном дереве
Source Оbject -класс Используется для указания на объект-источник, если он не является элементом WPF и поэтому нельзя применить ElementName

Способы привязки рассмотрим на примерах.

  • Добавьте к решению DataBinding командой File/Add/New Project новый проект WPF Application с именем ElementWithObject и назначьте его стартовым

  • Настройте открывающий дескриптор окна Window1 нового проекта так
<Window x:Class="ElementWithObject.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Height="300" 
    Width="300"
    Title="Привязка элемента к объекту" 
    MinHeight="300" 
    MinWidth="300"
    WindowStartupLocation="CenterScreen"
    >  
    <Grid>
    </Grid>
</Window>
  • Добавьте к разметке файла Window1.xaml логический ресурс для обеспечения классического цвета фона окна и присоедините его к свойству Background сетки Grid
<Window x:Class="ElementWithObject.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Height="300" 
    Width="300"
    Title="Привязка элемента к объекту" 
    MinHeight="300" 
    MinWidth="300"
    WindowStartupLocation="CenterScreen"
    >   
    <Window.Resources>
        <SolidColorBrush x:Key="ControlColorBrush" 
            Color="{x:Static SystemColors.ControlColor}" />
    </Window.Resources>
    <Grid Background="{StaticResource ResourceKey=ControlColorBrush}">
    </Grid>
</Window>

Вкладка Page1. Использование логического ресурса без привязки

Вначале создадим вкладку для демонстрации способа подключения статического ресурса без использования привязки.

  • Добавьте в разметку контейнер TabControl с вкладкой Page1 следующего содержания
<Grid Background="{StaticResource ResourceKey=ControlColorBrush}">
        <TabControl>
            <!-- Page1. Использование логического ресурса без привязки -->
            <TabItem Header="Page1">
                <TabItem.Resources>
                    <ImageBrush x:Key="flower1"
                        ImageSource="Images/flower1.jpg"
                        Stretch="UniformToFill"
                        Opacity="1"
                        />
                </TabItem.Resources>
                <Rectangle 
                    Stroke="Red"
                    StrokeThickness="5.0" 
                    Opacity="1"
                    Fill="{StaticResource flower1}" />
            </TabItem>
        </TabControl>
    </Grid>
  • В панели Solution Explorer добавьте к корню проекта ElementWithObject командой контекстного меню Add/New Folder папку с именем Images
  • В панели Solution Explorer для папки Images вызовите контекстное меню и скопируйте в нее командой Add/Existing Item из прилагаемого каталога Source файл flower1.jpg
  • Выделите файл flower1.jpg и в панели Properties проверьте его настройки в оболочке. Они должны быть такими
    • Build Action=Resource
    • Copy to Output Directory=Do not copy
  • Запустите приложение - представление вкладки будет таким

Здесь мы пока не применяли механизм привязки, но вспомнили использование ресурсов.

Вкладка Page2. Связывание целевого элемента с исходным объектом через логический ресурс

Когда встает вопрос привязки визуального элемента к объекту, в отличии от привязки элемента к элементу, то в выражении привязки для обозначения источника нужно использовать взамен атрибута ElementName другой атрибут - Source (или RelativeSource ). В следующем примере используем в качестве посредника привязки логический ресурс.

  • В панели Solution Explorer для папки Images вызовите контекстное меню и скопируйте в нее командой Add/Existing Item из прилагаемого каталога Source файл flower2.jpg
  • Выделите файл flower2.jpg и в панели Properties проверьте его настройки в оболочке. Они должны быть такими
    • Build Action=None
    • Copy to Output Directory=Copy if newer
  • В пространство имен файла Window1.xaml.cs добавьте новый класс Pictures со следующим процедурным кодом
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
    
namespace ElementWithObject
{
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }
    }
    
    class Pictures
    {
        // Поле
        public static ImageBrush picture = new ImageBrush();
    
        static Pictures()
        {
            picture.ImageSource = new BitmapImage(
                new Uri(@"Images\flower2.jpg", UriKind.Relative));
            picture.Stretch = Stretch.UniformToFill;
            picture.Opacity = 1.0D;
        }
    
        // Свойство
        public static ImageBrush Picture { get { return picture; } }
    }
}
  • Добавьте в заголовок дескриптора Window запись импортирования пространства имен приложения для доступа к свойству класса Pictures из разметки
<Window x:Class="ElementWithObject.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Height="300" 
    Width="300"
    Title="Привязка элемента к объекту" 
    MinHeight="300" 
    MinWidth="300"
    WindowStartupLocation="CenterScreen"
        
    xmlns:local="clr-namespace:ElementWithObject"
    >   
    ..............................................................
        
</Window>
  • Добавьте в контейнер TabControl новую вкладку с именем Page2 с привязкой логического ресурса к фону кнопки
<!-- Page2. Связывание целевого элемента с исходным
                        объектом через логический ресурс -->
            <TabItem Header="Page2">
                <TabItem.Resources>
                    <TextBlock x:Key="title2"
                        FontSize="16"
                        TextAlignment="Center"
                        FontWeight="Bold">
                        <TextBlock.Foreground>
                            <SolidColorBrush Color="Yellow" />
                        </TextBlock.Foreground>
                        Связывание целевого элемента
                        <LineBreak />
                        с исходным объектом
                        <LineBreak />
                        через логический ресурс
                    </TextBlock>
                    <local:Pictures x:Key="flower2" />
                </TabItem.Resources>
                <Button 
                    Content="{StaticResource ResourceKey=title2}"
                    Background="{Binding Source={StaticResource flower2},
                                         Path=Picture, Mode=OneWay}" />
            </TabItem>
  • Запустите проект с вкладкой Page2 - область вывода будет такой

Алексей Бабушкин
Алексей Бабушкин

При выполнении в лабораторной работе упражнения №1 , а именно при выполнении нижеследующего кода:

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

using Microsoft.Xna.Framework.Graphics;

   

namespace Application1

{

    public partial class MainForm : Form

    {

        // Объявим поле графического устройства для видимости в методах

        GraphicsDevice device;

   

        public MainForm()

        {

            InitializeComponent();

   

            // Подпишемся на событие Load формы

            this.Load += new EventHandler(MainForm_Load);

   

            // Попишемся на событие FormClosed формы

            this.FormClosed += new FormClosedEventHandler(MainForm_FormClosed);

        }

   

        void MainForm_FormClosed(object sender, FormClosedEventArgs e)

        {

            //  Удаляем (освобождаем) устройство

            device.Dispose();

            // На всякий случай присваиваем ссылке на устройство значение null

            device = null;       

        }

   

        void MainForm_Load(object sender, EventArgs e)

        {

            // Создаем объект представления для настройки графического устройства

            PresentationParameters presentParams = new PresentationParameters();

            // Настраиваем объект представления через его свойства

            presentParams.IsFullScreen = false; // Включаем оконный режим

            presentParams.BackBufferCount = 1;  // Включаем задний буфер

                                                // для двойной буферизации

            // Переключение переднего и заднего буферов

            // должно осуществляться с максимальной эффективностью

            presentParams.SwapEffect = SwapEffect.Discard;

            // Устанавливаем размеры заднего буфера по клиентской области окна формы

            presentParams.BackBufferWidth = this.ClientSize.Width;

            presentParams.BackBufferHeight = this.ClientSize.Height;

   

            // Создадим графическое устройство с заданными настройками

            device = new GraphicsDevice(GraphicsAdapter.DefaultAdapter, DeviceType.Hardware,

                this.Handle, presentParams);

        }

   

        protected override void OnPaint(PaintEventArgs e)

        {

            device.Clear(Microsoft.Xna.Framework.Graphics.Color.CornflowerBlue);

   

            base.OnPaint(e);

        }

    }

}

Выбрасывается исключение:

Невозможно загрузить файл или сборку "Microsoft.Xna.Framework, Version=3.0.0.0, Culture=neutral, PublicKeyToken=6d5c3888ef60e27d" или один из зависимых от них компонентов. Не удается найти указанный файл.

Делаю все пунктуально. В чем может быть проблема?