Опубликован: 05.08.2010 | Уровень: специалист | Доступ: платный
Самостоятельная работа 13:

Ресурсы в WPF

< Самостоятельная работа 12 || Самостоятельная работа 13: 123456 || Лекция 1 >

Использование библиотеки ресурсов

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

  • Командой меню File/Add/New Project оболочки добавьте к решению новый проект с именем UseLibraryResource по шаблону WPF Application и назначьте его стартовым командой Set as StartUp Project
  • В панели Solution Explorer раскройте узел проекта UseResource первого упражнения и перетащите из него мышью папку Images на корневой узел проекта UseLibraryResource. Оболочка скопирует эту папку вместе с содержимым в наш новый проект UseLibraryResource
  • Выделяя последовательно файлы рисунков в папке Images, установите (или проверьте) в панели Properties для них следующие свойства
    • FACE02.ICO, FACE04.ICO:
      • Build Action=Resource
      • Copy to Output Directory=Do not copy
    • 10440.jpg:
      • Build Action=None
      • Copy to Output Directory=Copy if newer
  • В панели Solution Explorer выделите узел проекта UseLibraryResource и щелкните на пиктограмме Show All Files этой панели для раскрытия дерева файлов проекта
  • Раскройте узел UseLibraryResource/bin/Debug и убедитесь, что он не содержит пока никаких файлов

  • В панели Solution Explorer вызовите контекстное меню для узла References и выполните команду Add Reference, чтобы вызвать окно подключения библиотечных сборок
  • В окне Add Reference откройте вкладку Projects, выделите сборку LibraryResource.dll и щелкните на кнопке OK

Ссылка на эту библиотеку будет подключена к текущему проекту UseLibraryResource и появится в его узле References.

  • Откомпилируйте (или запустите) пустой проект UseLibraryResource и в панели Solution Explorer щелкните на кнопке Refresh, чтобы обновить представление панели

Мы видим, что оболочка скопировала готовую библиотечную сборку LibraryResource.dll в один каталог с исполнимой сборкой UseLibraryResource.exe. Важно помнить, что для нормальной работы приложения, использующего ресурсы нашей библиотечной сборки (или нуждающегося в любой другой пользовательской библиотеке), файл LibraryResource.dll при развертывании на клиентской машине всегда должен находиться в одном каталоге с исполнимым файлом приложения. Либо при развертывании библиотеку нужно будет размещать и специальным образом регистрировать в глобальном хранилище сборок GAC (Global Assembly Cache) на клиентской машине, что гораздо сложнее (но выполнимо).

  • Заполните файл Window1.xaml проекта UseLibraryResource следующей разметкой
<Window x:Class="UseLibraryResource.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:resLib="clr-namespace:LibraryResource;assembly=LibraryResource"
    Title="UseLibraryResource" 
    MinHeight="300" 
    MinWidth="300"
    Height="300" 
    Width="300"
    WindowStartupLocation="CenterScreen"
    Background="{x:Static SystemColors.MenuBarBrush}">
    
    <!-- Содержимое окна -->
    <StackPanel>
        <!-- Это не ресурс, а элемент визуального дерева -->
        <TextBlock HorizontalAlignment="Center"
                   FontSize="18"
                   FontWeight="Bold"
                   Margin="0,0,0,5">
            Применение ресурсов
        </TextBlock>
            
        <!-- Синтаксис подключения ресурсов как статических полей и свойств библиотеки по ключу -->
        <Label HorizontalAlignment="Center"
               Content="{DynamicResource {x:Static resLib:CustomResources.Title1Key}}" />
        <Button Name="btn1" Padding="5" Margin="5"
                FontWeight="Bold" FontSize="16" 
                Foreground="{DynamicResource {x:Static resLib:CustomResources.ForegroundBrushKey}}"
                Background="{DynamicResource {x:Static resLib:CustomResources.BackgroundBrushKey}}"
                Content="Только DynamicResource" />
        <Button Name="btn2" Padding="5" Margin="5" 
                FontWeight="Bold" FontSize="16" 
                Foreground="{DynamicResource {x:Static resLib:CustomResources.ForegroundBrushKey}}"
                Background="{DynamicResource {x:Static resLib:CustomResources.BackgroundBrushKey}}"
                Content="Только DynamicResource" />
    
        <!-- Синтаксис подключения ресурсов из ресурсного словаря библиотеки по имени ресурса -->
        <Label HorizontalAlignment="Center"
               Content="{DynamicResource {ComponentResourceKey
                         TypeInTargetAssembly={x:Type resLib:CustomResources},
                         ResourceId=Title2}}" />
        <Button Click="Button_Click" Padding="5" Margin="5" 
                FontWeight="Bold" FontSize="16"
                Foreground="{DynamicResource {ComponentResourceKey
                             TypeInTargetAssembly={x:Type resLib:CustomResources},
                             ResourceId=ForegroundBrush2}}"
                Background="{DynamicResource {ComponentResourceKey
                             TypeInTargetAssembly={x:Type resLib:CustomResources},
                             ResourceId=BackgroundBrush2}}"
                Content="Только DynamicResource" />
        <Button Click="Button_Click" Padding="5" Margin="5" 
                FontWeight="Bold" FontSize="16" 
                Foreground="{DynamicResource {ComponentResourceKey
                             TypeInTargetAssembly={x:Type resLib:CustomResources},
                             ResourceId=ForegroundBrush2}}"
                Background="{DynamicResource {ComponentResourceKey
                             TypeInTargetAssembly={x:Type resLib:CustomResources},
                             ResourceId=BackgroundBrush2}}"
                Content="Только DynamicResource" />
    </StackPanel>
</Window>
  • Переключите редактор разметки в режим Design - оболочка видит библиотечные ресурсы уже на этапе проектирования

  • Заполните файл Window1.xaml.cs проекта UseLibraryResource следующим процедурным кодом (код файла Window1.xaml.cs приводится целиком)
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
    
using LibraryResource;// Подключаем пространство имен библиотеки с ресурсами
    
namespace UseLibraryResource
{
    public partial class Window1 : Window
    {
        public Window1()
        {
            // Инициализация интерфейсных элементов
            InitializeComponent();
    
            // Создаем и добавляем программно объекты ресурсов в коллекцию окна
            //
            // ... alternateColor
            SolidColorBrush solidColorBrush = new SolidColorBrush();
            solidColorBrush.Color = Colors.Blue;
            this.Resources.Add("alternateColor", solidColorBrush);
            //
            // ... alternateImage
            ImageBrush imageBrush = new ImageBrush();
            imageBrush.ImageSource = new BitmapImage(
                new Uri(@"Images\10440.jpg", UriKind.Relative)
                );
            imageBrush.TileMode = TileMode.Tile;
            imageBrush.ViewportUnits = BrushMappingMode.Absolute;// Не путать с ViewboxUnits
            imageBrush.Viewport = new Rect(0, 0, 32, 32);
            imageBrush.Opacity = 0.5D;// Можно и без D, преобразует неявно из float в double
            this.Resources.Add("alternateImage", imageBrush);
    
            // Регистрируем обработчики программно
            btn1.Click += btn1_Click;
            btn2.Click += btn2_Click;
        }
    
        // Используем внешние ресурсы
        void btn1_Click(object sender, RoutedEventArgs e)
        {
            CustomResources.changeResourceKeyFlag =
                !CustomResources.changeResourceKeyFlag;
            btn1.Foreground = btn1.TryFindResource(
                CustomResources.ForegroundBrushKey) as SolidColorBrush;
            btn1.Background = (ImageBrush)btn1.TryFindResource(
                CustomResources.BackgroundBrushKey);
        }
    
        // Используем внешние ресурсы
        void btn2_Click(object sender, RoutedEventArgs e)
        {
            CustomResources.changeResourceKeyFlag =
                !CustomResources.changeResourceKeyFlag;
            try
            {
                btn2.Foreground = btn2.FindResource(
                    CustomResources.ForegroundBrushKey) as SolidColorBrush;
                btn2.Background = (ImageBrush)btn2.FindResource(
                    CustomResources.BackgroundBrushKey);
            }
            catch (Exception exc)
            {
                MessageBox.Show(exc.Message);
            }
        }
    
        bool changeResourceFlag2 = true;
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            // Приводим ссылку к типу Button
            Button btn = sender as Button;
            if (btn == null)
                return;
    
            if (changeResourceFlag2)
            {
                // Используем внутренние ресурсы окна
                btn.Foreground= (SolidColorBrush)this.Resources["alternateColor"];
                btn.Background = (ImageBrush)this.Resources["alternateImage"];
            }
            else 
            {
                // Используем внешние ресурсы
                btn.Foreground = btn.TryFindResource(
                    CustomResources.ForegroundBrushKey) as SolidColorBrush;
                btn.Background = (ImageBrush)btn.TryFindResource(
                    CustomResources.BackgroundBrushKey);
            }
            changeResourceFlag2 = !changeResourceFlag2;// Готовим другой вариант
        }
    }
}
  • Запустите и испытайте работу приложения UseLibraryResource, разберитесь с кодом

Не стоит забывать, что при извлечении ресурсов через ключи типа ComponentResourceKey следует всегда использовать обязательно динамические, а не статические ресурсы.


< Самостоятельная работа 12 || Самостоятельная работа 13: 123456 || Лекция 1 >
Алексей Бабушкин
Алексей Бабушкин

При выполнении в лабораторной работе упражнения №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" или один из зависимых от них компонентов. Не удается найти указанный файл.

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

Dmitriy Ivanchenko
Dmitriy Ivanchenko
Украина, Кировоград, Виктория-П, 2011
Татьяна Ковалюк
Татьяна Ковалюк
Украина, Киев, Киевский политехнический институт, 1974