Неразделяемые ресурсы

93

Обычно когда ресурс используется во множестве мест, применяется один и тот же экземпляр объекта. Такое поведение — называемое разделением — оказывается, как правило, тем, что нужно. Тем не менее, допустимо также указывать анализатору на необходимость создания отдельного экземпляра объекта при каждом его использовании. Разделение отключается с помощью атрибута Shared:

<ImageBrush х:Кеу="TileBrush" х:Shared="False" ...></ImageBrush>

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

Еще одна причина применения неразделяемых ресурсов — необходимость повторного использования объекта таким способом, который в противном случае невозможен. Например, это позволяет определить элемент (вроде Image или Button) как ресурс и затем отображать его в нескольких местах внутри окна.

Опять-таки, обычно это не самый лучший подход. Например, для повторного использования элемента Image целесообразнее сохранить соответствующий фрагмент информации (такой как объект BitmapImage, идентифицирующий источник изображения) и затем разделить его между множеством элементов Image. Если просто нужно стандартизировать элементы управления так, чтобы они совместно использовали одни и те же свойства, гораздо лучше применять стили. Стили предоставляют возможность создавать идентичные или почти идентичные копии любого элемента, а также переопределять значения свойств, когда они не подходят, и присоединять конкретные обработчики событий, чего нельзя делать в случае простого клонирования элемента, использующего неразделяемый ресурс.

Доступ к ресурсам в коде

Обычно ресурсы определяются и используются в разметке. Однако при необходимости с коллекцией ресурсов можно работать и в коде.

Как уже было показано, элементы можно извлекать из коллекции ресурсов по имени. Однако при таком подходе должна использоваться коллекция ресурсов правильного элемента. Как упоминалось ранее, на разметку это ограничение не распространяется.

Элемент управления вроде кнопки может извлекать ресурс, не зная точно, где тот определен. Когда свойству Background кнопки присваивается кисть, среда WPF проверяет коллекцию ресурсов кнопки на предмет наличия в ней ресурса по имени TileBrush, затем коллекцию ресурсов содержащего ее элемента StackPanel, после чего коллекцию ресурсов содержащего ее окна. (Этот процесс фактически продолжается поиском в ресурсах приложения и системы.)

Искать ресурс подобным образом можно с помощью метода FrameworkElement.FindResource(). Ниже приведен пример, в котором при срабатывании события Click производится поиск ресурса кнопки (или одного из ее контейнеров более высокого уровня):

private void cmdChange_Click(object sender, RoutedEventArgs e)
{
   Button cmd = (Button)sender;
   ImageBrush brush = (ImageBrush)cmd.FindResource("TileBrush");
}

Вместо FindResource() можно также использовать метод TryFindResource(), который вместо генерации исключения, если ресурс не найден, возвращает ссылку null. Кстати, ресурсы допускается добавлять программно. Для этого необходимо выбрать элемент для размещения ресурса и вызвать метод Add() коллекции ресурсов. Тем не менее, гораздо чаще ресурсы определяются в разметке.

Пройди тесты
Лучший чат для C# программистов