|
При выполнении в лабораторной работе упражнения №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
Вкладка Page10. Привязка RelativeSource к свойствам родительского элемента
-
Добавьте в контейнер TabControl файла Window1.xaml новую вкладку с именем Page10, которую заполните так
<!-- Относительная привязка RelativeSource к источнику -->
<TabItem Header="Page10">
<StackPanel>
<Grid Tag="Привязка к Grid по синтаксису элементов свойств">
<Button Margin="5" FontSize="10">
<Button.Content>
<Binding Path="Tag" Mode="OneWay">
<Binding.RelativeSource>
<RelativeSource Mode="FindAncestor"
AncestorType="Grid"
AncestorLevel="1" />
</Binding.RelativeSource>
</Binding>
</Button.Content>
</Button>
</Grid>
<Grid Tag="Привязка к Grid по синтаксису расширения разметки">
<Button Margin="5" FontSize="10"
Content="{Binding Path=Tag,
RelativeSource={RelativeSource
Mode=FindAncestor,
AncestorType=Grid,
AncestorLevel=1},
Mode=OneWay}" />
</Grid>
<!-- Привязка к свойству заголовка окна
по синтаксису элементов свойств -->
<TextBlock TextAlignment="Center">
<TextBlock.Text>
<Binding Path="Title" Mode="OneWay">
<Binding.RelativeSource>
<RelativeSource Mode="FindAncestor"
AncestorType="Window" />
</Binding.RelativeSource>
</Binding>
</TextBlock.Text>
</TextBlock>
<Label HorizontalAlignment="Center">
<Label.Content>
<Binding Path="Title" Mode="OneWay">
<Binding.RelativeSource>
<RelativeSource Mode="FindAncestor"
AncestorType="{x:Type Window}">
</RelativeSource>
</Binding.RelativeSource>
</Binding>
</Label.Content>
</Label>
<!-- Привязка к свойству заголовка окна
по синтаксису расширения разметки -->
<TextBlock TextAlignment="Center"
Text="{Binding Path=Title,
RelativeSource=
{RelativeSource FindAncestor,
AncestorType={x:Type Window}},
Mode=OneWay}" />
<Label HorizontalAlignment="Center"
Content="{Binding Path=Title,
RelativeSource=
{RelativeSource Mode=FindAncestor,
AncestorType=Window},
Mode=OneWay}" />
</StackPanel>
<TabItem>Свойство Content первых двух кнопок мы привязали к свойству Tag родительского элемента Grid. Остальные 4 элемента привязаны к свойству Title окна. Свойство AncestorLevel по умолчанию равно 1, поэтому там, где не требуется явно задать иное значение, его можно опустить. В синтаксисе расширения разметки атрибут Mode=FindAncestor можно писать без параметра Mode.
-
Запустите приложение - вкладка Page10 будет выглядеть так
Вкладка Page11. Привязка RelativeSource к вложенным свойствам
Приведем пример, в котором привязка выполняется к свойству родителя, вложенному в него из другого объекта.
-
Добавьте в контейнер TabControl файла Window1.xaml новую вкладку с именем Page11, которую заполните так
<!-- Относительная привязка RelativeSource -->
<TabItem Header="Page11" Selector.IsSelected="True">
<DockPanel LastChildFill="True">
<StackPanel DockPanel.Dock="Top">
<TextBlock FontSize="16"
TextAlignment="Center" Margin="0,5,0,5">
<TextBlock.Foreground>
<SolidColorBrush Color="Purple" />
</TextBlock.Foreground>
Привязка с помощью RelativeSource
</TextBlock>
<ListBox Foreground="Red" SelectionMode="Multiple" Height="60">
<CheckBox Selector.IsSelected="False"
IsChecked="{Binding RelativeSource={RelativeSource Mode=Self},
Path=(Selector.IsSelected), Mode=TwoWay}"
Foreground="{Binding Path=Foreground,
RelativeSource=
{RelativeSource Mode=FindAncestor,
AncestorType=ListBox},
Mode=OneWay}">
1) Это еще флажок, элемент списка правее
</CheckBox>
<CheckBox ListBox.IsSelected="False"
IsChecked="{Binding RelativeSource={RelativeSource
Mode=FindAncestor,
AncestorLevel=1,
AncestorType={x:Type ListBoxItem}},
Path=IsSelected, Mode=TwoWay}"
Foreground="{Binding Path=Foreground,
RelativeSource=
{RelativeSource Mode=FindAncestor,
AncestorType=ListBox},
Mode=OneWay}">
2) Это еще флажок, элемент списка правее
</CheckBox>
<CheckBox
Foreground="{Binding Path=Foreground,
RelativeSource=
{RelativeSource FindAncestor,
AncestorType=ListBox},
Mode=OneWay}">
3) Это еще флажок, элемент списка правее
</CheckBox>
<ListBoxItem IsSelected="False">
<CheckBox
IsChecked="{Binding RelativeSource={RelativeSource
AncestorType={x:Type ListBoxItem}},
Path=IsSelected, Mode=TwoWay}"
Foreground="{Binding Path=Foreground,
RelativeSource=
{RelativeSource FindAncestor,
AncestorType=ListBox},
Mode=OneWay}">
4) Это еще флажок, элемент списка правее
</CheckBox>
</ListBoxItem>
</ListBox>
</StackPanel>
<RichTextBox
Margin="0,5,0,0"
ScrollViewer.VerticalScrollBarVisibility="Auto">
</RichTextBox>
</DockPanel>
</TabItem>Поскольку вкладка <TabItem> может содержать только один элемент, мы упаковали ее содержимое в компоновочную панель <DockPanel>. В качестве содержимого контейнера <DockPanel> определили два элемента: компоновочную панель <StackPanel> и контейнер <RichTextBox>, где чуть позже разместим краткую инструкцию пользователя (для тренировки). Настройка <StackPanel DockPanel.Dock="Top"> приклеивает эту панель к верхней части родителя <DockPanel>, а настройка <DockPanel LastChildFill="True"> заставляет элемент <RichTextBox> занять всю остальную оставшуся свободной часть.
На первом месте в контейнере <StackPanel> размещен элемент <TextBlock> для вывода заголовка. Далее следует элемент списка <ListBox>, который в качестве своих дочерних объектов содержит элементы флажков <CheckBox>. Интересно то, что первые три элемента списка не указаны явно и только последний элемент указан.
Если не создавать контейнер элемента ListBoxItem явно, то WPF сама создает его неявно и присваивает его свойству IsSelected значение Selector.IsSelected. Только один раз в момент создания свойство Selector.IsSelected считывается привязанными элементами. Но далее при изменении выбора элемента это свойство не обновляется. Чтобы показать, что Selector.IsSelected действительно не обновляется, свойство IsChecked первого флажка связывается с Selector.IsSelected первого элемента ListBoxItem в соответствии с режимом RelativeSource Mode=Self.
Когда пользователь меняет выделение первого элемента ListBoxItem, элемент CheckBox остается в прежнем состоянии. И наоборот, установка или снятие флажка в первом CheckBox не влияет на смену выделения родителя ListBoxItem. Обратите внимание, что в выражении привязки первого CheckBox значение привязываемого вложенного свойства заключается в круглые скобки.
Итак, когда контейнер элемента не создается явно, следует использовать вложенное свойство зависимостей Selector.IsSelected для начального выделения элемента в Selector. Объекты TabItem, ListBox и ComboBox являются контейнерами для списковых элементов управления и наследуют от Selector. Поэтому, когда их дочерние элементы заданы явно, то каждый имеет свое свойство IsSelected. К этому свойству мы и привязываемся во втором и четвертом элементах списка, что дает взаимную синхронизацию выделения флажка и элемента списка.
-
Запустите приложение - пока вкладка Page11 может выглядеть так
Замечание. Если из заголовка вкладки
<TabItem Header="Page11" Selector.IsSelected="True">удалить атрибут Selector.IsSelected="True", то синхронная работа второго элемента нарушается (не знаю, почему...).
Свойство Foreground каждого элемента списка, заданного явно или неявно, мы связали с одноименным свойством контейнера <ListBox>, в котором задали ему значение Red для обеспечения контраста надписи на выделенном элементе (и для тренировки). Эту привязку мы тоже выполнили по рассматриваемой технологии RelativeSource.
Последним в компоновочном контейнере <DockPanel> мы забронировали элемент <RichTextBox>, который обеспечивает поддержку документов нефиксированного формата <FlowDocument>. Наша задача - создать краткую инструкцию 'чего-то... чего-то', разместить ее во внешнем файле как элемент <FlowDocument> и загрузить в контейнер <RichTextBox> во время выполнения. К теме привязки этот кусочек задачи отношения не имеет, но для тренировки, чтобы заполнить оставшееся на вкладке (и в голове) вакантное место, решим ее.
Там шпионки с крепким телом,
Ты их в дверь - они в окно!
Говори, что с 'этим делом'
Мы покончили давно!
(В.С. Высоцкий)
-
Добавьте к текущему проекту командой Project/Add New Item новый XAML -файл с именем Instruct.xaml (не забудьте изменить расширение файла c xml на xaml )
-
Выделите в Solution Explorer новый файл Instruct.xaml и измените через панель Properties его свойства на
- Build Action = None
- Copy to Output Directory=Copy if newer
-
Удалите в файле Instruct.xaml сгенерированное мастером содержимое и заполните его следующей разметкой (чем бы то нибыло, абы-кабы, аты-баты и т.д.)
<FlowDocument FontSize="11" Background="White"
>
<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>-
Запустите приложение - компилятор (синтаксический анализатор) начинает ругаться, что не понимает конструкцию файла и не может преобразовать ее в объектный код. Текстовый редактор оболочки тоже зашелся в истерике, потому что не видит библиотеку WPF
-
Добавьте в открывающий дескриптор <FlowDocument> подключение пространства имен WPF -библиотеки
<FlowDocument FontSize="11" Background="White"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
.............................................
</FlowDocument>;
Откомпилируйте решение командой Build/Build Solution - вроде бы все успокоилось
Если бы мы поместили содержимое файла Instruct.xaml сразу внутрь контейнера <RichTextBox>...</RichTextBox>, то в дескрипторе окна <Window> уже есть такое подключение и ничего специального предпринимать бы не пришлось. И все бы сразу заработало, можете так и попробовать. Но чтобы не захломлять разметку вкладки Page11, мы пошли окружным путем и решили вынести документ в отдельный файл Instruct.xaml. В наказание за инициативу нам еще нужно будет этот файл подключить к контейнеру <RichTextBox>. Сделать это можно в процедурном коде или в разметке - через словарь ресурсов. Применим поочередно оба способа.
Подключение документа через процедурный код
-
Дополните в разметке вкладки Page11 контейнер <RichTextBox> именем и зарегистрируйте обработчик события Loaded так
<RichTextBox Name="documentReader" Loaded="documentReader_Loaded"
Margin="0,5,0,0"
ScrollViewer.VerticalScrollBarVisibility="Auto">
</RichTextBox>-
В разметке на записи регистрации обработчика события Loaded контейнера <RichTextBox> вызовите контекстное меню и командой Navigate to Event Handler создайте в файле Window1.xaml.cs заготовку этого обработчика, которую заполните следующим кодом
private void documentReader_Loaded(object sender, RoutedEventArgs e)
{
String fileName = "Instruct.xaml";
FileStream xamlFile = new FileStream(fileName, FileMode.Open, FileAccess.Read);
FlowDocument content = XamlReader.Load(xamlFile) as FlowDocument;
documentReader.Document = content;
xamlFile.Close();
}-
В начало файла Window1.xaml.cs добавьте подключение пространств имен для используемых в обработчике классов и перечислений
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;
// Дополнительные пространства имен
using System.Windows.Markup;// Для класса XamlReader
using System.IO; // Для класса FileStream,
// перечислений FileMode и FileAccess
namespace ElementWithObject
{
public partial class Window1 : Window
{
....................................................
}
}-
Запустите приложение с вкладкой Page11 - все работает как надо и снимок экрана может быть таким



