|
При выполнении в лабораторной работе упражнения №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" или один из зависимых от них компонентов. Не удается найти указанный файл. Делаю все пунктуально. В чем может быть проблема? |
Основы привязки данных в WPF
Подключение документа через ресурс
Теперь ту же задачу подключения документа к контейнеру <RichTextBox> быстренько повторим с использованием механизма ресурсов, чтобы вспомнить молодость. При этом нам не придется писать ни строчки процедурного кода, все выполним в разметке. Чтобы не вмешиваться в процедурный код, просто удалим регистрацию обработчика события Loaded из разметки элемента RichTextBox. Пусть обработчик существует как обычный незадействованный метод класса Window1 и никуда не встревает со своими услугами. А компилятор тоже будет молчать.
| Было |
<RichTextBox Name="documentReader" Loaded="documentReader_Loaded"
Margin="0,5,0,0"
ScrollViewer.VerticalScrollBarVisibility="Auto">
</RichTextBox> |
|---|---|
| Стало |
<RichTextBox Name="documentReader"
Margin="0,5,0,0"
ScrollViewer.VerticalScrollBarVisibility="Auto">
</RichTextBox> |
Имя удалять не будем, потому что на него ссылается код обработчика. Если хотим убрать и имя, тогда нужно очистить или вообще удалить обработчик documentReader_Loaded() из класса Window1 (кому как, а лично мне это делать жалко, код-то вымучен бессонными ночами и недопитыми литрами. Хотя с допитыми может быть получилось бы лучше).
-
В панели Solution Explorer выделите корневой узел текущего проекта и через меню оболочки командой Project/Add Resource Dictionary добавьте новый файл с именем по умолчанию Dictionary1.xaml
-
Выделите в Solution Explore новый файл Dictionary1.xaml и проверьте через панель Properties его свойства, чтобы они были такими
- Build Action = Page
- Copy to Output Directory=Do not copy
-
Скопируйте из файла Instruct.xaml в новый файл Dictionary1.xaml все содержимое с разметкой документа <FlowDocument> и обязательно добавьте в его открывающем дескрипторе ключ ресурса x:Key="instruct". При этом можете удалить, а можете и оставить, индивидуальное подключение пространств имен XAML, которое в дескрипторе ресурса уже присутствует (можете удалить любое из них или ничего не удалять)
Файл Dictionary1.xaml должен стать таким (текст неважен, важна разметка)
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
<FlowDocument x:Key="instruct" FontSize="11" Background="White"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
<List MarkerStyle="Decimal">
<ListItem>
<Paragraph>
Первый флажок двунаправленно привязан булевым свойством
IsChecked к вложенному логическому свойству Selector.IsSelected,
которое инициализируется один раз и больше не меняется.
Поэтому флажок и элемент списка меняются независимо.
Режим поиска родителя определен значением Mode=Self -
искать источник в том же элементе.
</Paragraph>
</ListItem>
<ListItem>
<Paragraph>
Второй флажок своим свойством IsChecked привязан двунаправленной
привязкой к свойству IsSelected своего ближайшего контейнера,
которым является элемент списка ListBoxItem,
поэтому и меняется синхронно с ним,
обеспечивая нормальную логику работы списка.
Режим поиска родителя определен значением Mode=FindAncestor -
искать источник в ближайшем родителе.
</Paragraph>
</ListItem>
<ListItem>
<Paragraph>
В третьем элементе списка флажок и элемент списка ListBoxItem
никак не связаны, поэтому изменяются автономно как в первом элементе,
где связь хоть и установлена, но источник Selector.IsSelected
остается постоянным
</Paragraph>
</ListItem>
<ListItem>
<Paragraph>
Четвертый элемент списка задается явно и флажок своим свойством
IsChecked привязан двунаправленной привязкой к свойству
IsSelected этого контейнера. Поэтому флажок и элемент списка
работают синхронно, как и в случае со вторым списком.
</Paragraph>
</ListItem>
</List>
</FlowDocument>
</ResourceDictionary>-
Дополните разметку элемента RichTextBox во вкладке Page11 следующей конструкцией подключения ресурса по синтаксису элемента свойства
<RichTextBox Name="documentReader"
Margin="0,5,0,0"
ScrollViewer.VerticalScrollBarVisibility="Auto">
<RichTextBox.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Dictionary1.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</RichTextBox.Resources>
<RichTextBox.Document>
<StaticResource ResourceKey="instruct" />
</RichTextBox.Document>
</RichTextBox>-
Запустите приложение - вкладка Page11 должна выглядеть точно так, как и в предыдущем случае подключения документа через процедурный код
Обращает на себя внимание применение элементов ListBox (ListBoxItem и List (ListItem). Оба называются списками. Но первый из них относится к элементам управления, поскольку служит для отображения информации и обеспечивает взаимодействие с пользователем. А второй - просто к элементам (хотя это и более общая категория), поскольку незримо участвует только в верстке документа. Да ладно, в конце-концов, - это касается только терминологии. Главное - не как называть, а правильно понимать и применять.
Вкладка Page12. Привязка RelativeSource в процедурном коде
Возьмем за основу привязку RelativeSource в разметке, а потом перенесем ее в процедурный код.
-
Добавьте в контейнер TabControl файла Window1.xaml новую вкладку с именем Page12, которую заполните следующей начальной разметкой, использующей привязку RelativeSource
<!-- Привязка RelativeSource в коде --<
<TabItem Header="Page12"<
<!-- Привязка Button.Content к StackPanel уровней 1 и 2 --<
<StackPanel Tag="Эта информация находится в StackPanel уровня 2"<
<StackPanel Tag="Эта информация находится в StackPanel уровня 1"<
<Button Margin="5"
Content="{Binding Path=Tag,
RelativeSource={RelativeSource
Mode=FindAncestor,
AncestorType=StackPanel,
AncestorLevel=1},
Mode=OneWay}" /<
<Button Margin="5"
Content="{Binding Path=Tag,
RelativeSource={RelativeSource
Mode=FindAncestor,
AncestorType=StackPanel,
AncestorLevel=2},
Mode=OneWay}" /<
</StackPanel<
<!-- Привязка TextBlock.Text к Window.Title --<
<Label<
Следующая информация находится в Window:
</Label<
<TextBlock Margin="5,0"<
<TextBlock.Text<
<Binding Path="Title" Mode="OneWay"<
<Binding.RelativeSource<
<RelativeSource Mode="FindAncestor"
AncestorType="Window" /<
</Binding.RelativeSource<
</Binding<
</TextBlock.Text<
</TextBlock<
</StackPanel<
</TabItem<-
Запустите приложение - вывод вкладки Page12 будет таким
-
Удалите привязку RelativeSource из элементов вкладки Page12 и присвойте привязываемым источникам имена для возможности адресации из процедурного кода
Окончательный вид вкладки Page12 будет таким
<!-- Привязка RelativeSource в коде -->
<TabItem Header="Page12" Selector.IsSelected="True">
<!-- Привязка Button.Content к StackPanel уровней 1 и 2 -->
<StackPanel Tag="Эта информация находится в StackPanel уровня 2">
<StackPanel Tag="Эта информация находится в StackPanel уровня 1">
<Button Margin="5" Name="button12level1" />
<Button Margin="5" Name="button12level2" />
</StackPanel>
<!-- Привязка TextBlock.Text к Window.Title -->
<Label>
Следующая информация находится в Window:
</Label>
<TextBlock Margin="5,0" Name="textBlock12" />
</StackPanel>
</TabItem>-
Добавьте в конструктор класса Window1 файла Window1.xaml.cs следующий процедурный код привязки RelativeSource
public Window1()
{
InitializeComponent();
//********************************************************
// Привязка RelativeSource для элементов вкладки Page12
//********************************************************
//
// button12level1
//
Binding binding = new Binding();
binding.Path = new PropertyPath("Tag");
binding.Mode = BindingMode.OneWay;
binding.RelativeSource = new RelativeSource(
RelativeSourceMode.FindAncestor, typeof(StackPanel), 1);
BindingOperations.SetBinding(button12level1, Button.ContentProperty, binding);
//
// button12level2
//
binding = new Binding("Tag");
binding.Mode = BindingMode.OneWay;
binding.RelativeSource = new RelativeSource(
RelativeSourceMode.FindAncestor, typeof(StackPanel), 2);
BindingOperations.SetBinding(button12level2, Button.ContentProperty, binding);
//
// textBlock12
//
binding = new Binding();
binding.Path = new PropertyPath("Title");
binding.Mode = BindingMode.OneWay;
binding.RelativeSource = new RelativeSource(
RelativeSourceMode.FindAncestor, typeof(Window), 1);
BindingOperations.SetBinding(textBlock12, TextBlock.TextProperty, binding);
}-
Запустите приложение - вывод вкладки Page12 остался в точности таким, как и с привязкой в разметк
Пока об основах привязки поговорили достаточно. Но это еще далеко не все. В следующих разделах мы рассмотрим вопросы более серьезного применения привязки: привязки WPF к объектам ADO.NET, привязки в шаблонах и т.д.


