|
При выполнении в лабораторной работе упражнения №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
Вкладка Page7. Присвоение свойству DataContext логической ссылки на ресурс
Вернемся к примеру вкладки Page2 и немного изменим его.
-
В панели Solution Explorer для папки Images вызовите контекстное меню и скопируйте в нее командой Add/Existing Item из прилагаемого каталога Source файл wood.jpg
-
Выделите файл wood.jpg и в панели Properties проверьте его настройки в оболочке. Они должны быть такими- Build Action=None
- Copy to Output Directory=Copy if newer
-
В файле Window1.xaml.cs в класс Pictures добавьте новый код
class Pictures
{
// Поле
public static ImageBrush picture = new ImageBrush();
public static ImageBrush picture1 = new ImageBrush();
static Pictures()
{
picture.ImageSource = new BitmapImage(
new Uri(@"Images\flower2.jpg", UriKind.Relative));
picture.Stretch = Stretch.UniformToFill;
picture.Opacity = 1.0D;
picture1.ImageSource = new BitmapImage(
new Uri(@"Images\wood.jpg", UriKind.Relative));
picture1.Stretch = Stretch.Uniform;
picture1.Opacity = 1.0D;
}
// Свойство
public static ImageBrush Picture { get { return picture; } }
public static ImageBrush Picture1 { get { return picture1; } }
}-
В коллекцию ресурсов разметки окна Window1 добавьте новый ресурс
<Window.Resources>
<SolidColorBrush x:Key="ControlColorBrush"
Color="{x:Static SystemColors.ControlColor}" />
<local:Pictures x:Key="wood" />
</Window.Resources>Вспомним, что при разработке вкладки Page2 мы уже добавили в заголовок дескриптора Window запись
xmlns:local="clr-namespace:ElementWithObject"
импортирования пространства имен приложения для доступа к свойству класса Pictures из разметки и теперь просто используем готовый псевдоним local.
-
В контейнер TabControl добавьте новую вкладку Page7 со следующей разметкой
<!-- Page7. Присвоение свойству DataContext
логической ссылки на ресурс -->
<TabItem Header="Page7"
DataContext=" {StaticResource ResourceKey=wood}">
<Button Background="{Binding Path=Picture1, Mode=OneWay}" />
</TabItem>Синтаксический анализатор ищет ресурс вначале в элементе его использования со свойством DataContext, а затем вверх по логическому дереву, поэтому мы расположили определение ресурса в словаре окна. То же самое присходит и с DataContext. Когда в выражении привязки атрибут Source пропущен, то WPF ищет определение источника в атрибуте DataContext вначале в элементе с выражением привязки и далее в родительских элементах, поэтому мы расположили DataContext в элементе <TabItem>.
-
Запустите приложение - результат вкладки Page7 выглядет так
Вкладка Page8. Управление свойством DataContext в процедурном коде
Обычно DataContext задается в коде. В частности, эта методика применяется к объектам ADO.NET, которые необходимо инициировать в коде и нельзя заполнять декларативно. Пока что без объектов ADO.NET рассмотрим этот способ. Естественно, что элемент, в котором будет задаваться свойство DataContext, должен иметь имя для возможности обращения из процедурного кода.
-
Добавьте в контейнер TabControl файла Window1.xaml новую вкладку с именем Page8
<!-- Page8. Управление свойством DataContext в процедурном коде -->
<TabItem Header="Page8">
<StackPanel Name="stackPanel8">
<TextBlock FontSize="16" TextDecorations="Underline"
TextAlignment="Center" Margin="0,5,0,15" Foreground="Red"
Text="Управление DataContext в коде"
/>
<StackPanel Orientation="Horizontal" Margin="5">
<Label Width="40"
Content="{Binding Path=Value, Mode=OneWay}"
/>
<Slider Name="slider8" Width="230"
Minimum="11" Maximum="54"
TickFrequency="2" TickPlacement="BottomRight"
IsSnapToTickEnabled="True"
/>
</StackPanel>
<Button
Margin="5"
Content="Подключить источник в DataContext"
Click="button8_Click">
</Button>
<TextBlock Margin="0,10"
Foreground="Blue"
FontSize="{Binding Path=Value, Mode=OneWay}"
Text="Simple Text"
/>
</StackPanel>
</TabItem>-
Расширьте класс Window1 следующим процедурным кодом
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
bool bindingFlag = false;
private void button8_Click(object sender, RoutedEventArgs e)
{
Button button = (Button)sender;
if (bindingFlag == false)
{
stackPanel8.DataContext = slider8;
button.Content = "Отключить источник в DataContext";
}
else
{
stackPanel8.DataContext = null;
button.Content = "Подключить источник в DataContext";
}
bindingFlag = !bindingFlag;
}
}-
Запустите приложение и испытайте работу вкладки Page8, внешний вид которой будет таким
Вкладка Page9. Создание и привязка пользовательского объекта
Мы можем создать пользовательский элемент управления и привязать его в коде или разметке. Приведем пример из Петцольда (стр. 633) и создадим простой пользовательский объект со свойством зависимости.
-
Добавьте в пространство имен ElementWithObject текущего проекта в файле Window1.xaml.cs новый класс SimpleElement
// Простой пользовательский элемент управления
class SimpleElement : FrameworkElement
{
// Статическое поле зависимости, базовое для свойства
public static DependencyProperty NumberProperty;
// Инициализация поля в статическом конструкторе
static SimpleElement()
{
NumberProperty = DependencyProperty.Register(
"Number",
typeof(double),
typeof(SimpleElement),
new FrameworkPropertyMetadata(0.0,
FrameworkPropertyMetadataOptions.AffectsRender));
}
// Свойство зависимости для доступа к полю
public double Number
{
get { return (double)this.GetValue(NumberProperty); }
set { this.SetValue(NumberProperty, value); }
}
// Жесткое кодирование размера области вывода
protected override Size MeasureOverride(Size availableSize)
{
return new Size(200, 20);
}
// Вывод значения свойства Number
protected override void OnRender(DrawingContext drawingContext)
{
drawingContext.DrawRectangle(Brushes.Yellow,
new Pen(Brushes.Red, 1.0),
new Rect(new Size(200, 20)));
drawingContext.DrawText(
new FormattedText(
Convert.ToInt32(Number).ToString(),
System.Globalization.CultureInfo.CurrentCulture,
FlowDirection.LeftToRight,
new Typeface("Arial"),
16.0D,
SystemColors.WindowTextBrush),
new Point(0, 0));
}
}При регистрации поля зависимости используется перечисление FrameworkPropertyMetadataOptions, которое определяет типы поведения свойства зависимости.
-
Добавьте в контейнер TabControl файла Window1.xaml новую вкладку с именем Page9, которую заполните так
<!-- Привязка пользовательского элемента управления -->
<TabItem Header="Page9">
<StackPanel>
<ScrollBar Orientation="Horizontal"
Margin="24"
Maximum="100"
LargeChange="10"
SmallChange="1"
Value="{Binding ElementName=simple9, Path=Number,
Mode=OneWayToSource}" />
<local:SimpleElement x:Name="simple9"
HorizontalAlignment="Center" />
<ScrollBar Name="scroll9"
Orientation="Horizontal"
Margin="24"
Maximum="100"
LargeChange="10"
SmallChange="1"
Value="{Binding ElementName=simple9, Path=Number,
Mode=TwoWay}" />
<local:SimpleElement
HorizontalAlignment="Center"
Number="{Binding ElementName=scroll9, Path=Value,
Mode=OneWay}" />
</StackPanel>
</TabItem>Здесь мы тоже просто используем ранее определенный псевдоним local импортирования пространства имен приложения для доступа к классу SimpleElement из разметки.
Разметка вводит в контейнер <StackPanel> две пары элементов: "библиотечный элемент прокрутки" - "пользовательский элемент". В секции определения первого пользовательского элемента вводится его имя в пространство имен XAML: x:Name="simple9", которое в дальнейшем используется в выражениях привязки другими элементами как имя объекта-источника. Применение обычного атрибута Name="simple9" будет считаться ошибкой.
Первый объект ScrollBar определяет одностороннюю привязку типа OneWayToSource со свойством Number пользовательского элемента и успешно обновляет это свойство при перемещении бегунка. Второй элемент ScrollBar определяет двухстороннюю привязку к свойству Number и успешно обновляет его в представлении двух пользовательских элементов, а также обновляется сам при изменении этого свойства. Однако перемещение второго бегунка хоть и изменяет свойство Number пользовательского элемента, но не влияет на состояние первого бегунка, поскольку определенная в первом ScrollBar привязка OneWayToSource обеспечивает передачу информации только в одну сторону.
-
Запустите приложение и убедитесь в сказанном (слава Петцольду!)
Привязка к источнику с помощью свойства RelativeSource
Класс System.Windows.Data. RelativeSource в выражении привязки целевого элемента указывает источник, которым является родительский объект, находящийся на расстоянии неопределенного (или определенного) числа шагов вверх по дереву элементов в направлении к корню. Этот объект также можно использовать и для привязки элемента к самому себе.
ип такой привязки задается свойством Mode из перечисления RelativeSourceMode, возможные значения которого следующие (Ancestor - предок)
| Значение | Описание |
|---|---|
| FindAncestor | Ссылается на источник с данными в визуальном дереве, который находится на неопределенное число шагов выше целевого элемента, содержащего выражение привязки. При использовании этого режима необходимо задавать дополнительные уточнения в свойствах класса RelativeSource, таких как AncestorType и AncestorLevel. Свойство AncestorType указывает тип источника привязки. Свойство AncestorLevel определяет, с какого вышестоящего уровня от приемника начинать поиск источника. Значение AncestorLevel=1 указывает ближайший к приемнику уровень начального поиска исходного объекта привязки |
| PreviousData | Когда ссылки на источники данных перечислены в списке, этот режим позволяет сменить текущий источник на предыдущий в списке |
| Self | Действует внутри элемента, содержащего выражение привязки, и позволяет сменить одно привязанное свойство на другое в том же элементе, т.е. привязать объект к самому себе |
| TemplatedParent | Если целевой элемент с выражением привязки находится внутри шаблона, такой режим привязывает его к данным шаблона |
На первый взгляд привязка со свойством RelativeSource кажется излишним усложнением. Ведь к источнику можно привязаться обычными средствами с помощью ElementName или Source. Однако такое возможно не всегда, в частности, при использовании шаблонов может выручить только привязка со свойством RelativeSource. Механизм шаблонов в этой теме не рассматривается, а вот применение данной привязки в традиционных задачах мы продемонстрируем на нескольких примерах.
Исполнение привязки со свойством RelativeSource, как и обычной, тоже возможно в двух синтаксисах: по синтаксису элементов свойств и по синтаксису расширения разметки.


