Опрос
Вы участвуете в программе Windows Insider?
Популярные новости
Обсуждаемые новости

29.10.2010 12:12 | deeper2k

В предыдущей статье мы узнали, как можно изменить цвет ленты, а также как работать с изображениями, используемыми на ленте. Теперь же мы вплотную подошли к довольно объёмной теме: коллекциям (или галереям) Windows Ribbon.

Также стоит сказать, что Арик Познански выпустил очередную версию библиотеки Windows Ribbon for WinForms под версией 2.5, в которой представлен новый механизм обработки событий ленты. Об этом будет рассказано ближе к концу данной статьи.

Итак, начнём.


DropDownGallery, SplitButtonGallery и InRibbonGallery
В этой части статьи я покажу, как использовать различные коллекции (галереи), доступные в Windows Ribbon Framework. Результатом будет очередной образец под названием "09-Galleries". Выглядит это так:





Коллекции элементов против коллекций команд
Коллекции, которые мы дальше рассмотрим, делятся на два вида: коллекции элементов и команд. В этом подзаголовке мы рассмотрим, в чём заключается разница между ними.

Коллекции элементов:

  • Элементы коллекции "простые", лишь текст и изображение, подобно элементам выпадающего списка (ComboBox).
  • Элементы имеют индекс, также существует понятие "Выбранный элемент" (англ. "Selected Item").
  • Коллекции элементов поддерживают превью. Это означает, что вы получаете уведомление (событие) "preview", когда перемещаете курсор над элементом, и уведомление "cancel preview", когда отменяете выбор.
  • Каждый элемент внутри такой коллекции имеет следующие свойства: Label, Image и Category ID.


Примечание: Элемент управления ленты "выпадающий список" (ComboBox) также является коллекцией элементов.

Коллекции команд

  • Элементы коллекции — на самом деле, команды.
  • Команды не имеют индекса, и поэтому не применяется понятие "Выбранный элемент".
  • Коллекции команд не поддерживают превью.
  • Каждый элемент в коллекции команд имеет следующие свойства: Command ID, Command Type и Category ID.


Примечание: В обоих типах коллекций применяется концепция категорий, см. статью 3 (часть, посвящённую элементу управления ComboBox) для подробностей.


Варианты коллекций
Теперь мы рассмотрим 3 имеющиеся варианта коллекций, каждый из которых может быть коллекцией элементов или команд. Повторю, что согласно MSDN, выпадающий список также рассматривается как коллекция элементов. Однако поскольку ранее мы уже рассмотрели ComboBox, я не буду упоминать о нём здесь.

DropDownGallery
Просто кнопка, щелчок по которой открывает список элементов. Сама кнопка не выполняет никаких действий. На изображении выше, самый левый элемент управления — это DropDownGallery.

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

Примечание: В статье 2 мы уже выяснили, что основным различием между "выпадающей" (DropDown) и "разделённой" (SplitButton) кнопками является наличие у SplitButton элемента по умолчанию.

InRibbonGallery
Элементы отображаются на ленте, кнопки не требуется. На изображениях вверху, самый правый элемент управления — это InRibbonGallery.


Командное пространство
Для полноты картины вы должны знать об одной дополнительной возможности: все 3 коллекции имеют командное пространство (англ. command space). Это секция внизу контрола, содержащая статически заданные команды. На первом изображении выше, у DropDownGallery есть кнопка в командном пространстве.


Использование коллекций
В следующих подзаголовках я покажу, как задавать коллекции в разметке ленты и использовать новые вспомогательные классы для упрощения работы с ними. Заметьте, что поскольку коллекции обладают множеством параметров, я продемонстрирую только наиболее типичные из них.


Использование DropDownGallery — разметка ленты
Здесь я покажу, как использовать DropDownGallery в качестве коллекции элементов с командным пространством.

Секция команд:

<Application.Commands>
  <Command Name='cmdTabMain' Id='1000' LabelTitle='Главная' />
  <Command Name='cmdGroupDropDownGallery' Id='1001' LabelTitle='Выпад' />
  <Command Name='cmdDropDownGallery' Id='1002' LabelTitle='Размер' >
    <Command.LargeImages>
      <Image>Res/Open32.bmp</Image>
    </Command.LargeImages>
    <Command.SmallImages>
      <Image>Res/Open16.bmp</Image>
    </Command.SmallImages>
  </Command>
  <Command Name='cmdCommandSpace' Id='1003' LabelTitle='Командное пространство' >
    <Command.LargeImages>
      <Image>Res/Save32.bmp</Image>
    </Command.LargeImages>
    <Command.SmallImages>
      <Image>Res/Save16.bmp</Image>
    </Command.SmallImages>
  </Command>
  …
</Application.Commands>

lication.Commands>
[/code]
Секция представлений:

[code]<Application.Views>
<Ribbon>
<Ribbon.Tabs>
<Tab CommandName='cmdTabMain'>
<Group CommandName='cmdGroupDropDownGallery' SizeDefinition='OneButton'>
<DropDownGallery CommandName='cmdDropDownGallery'
TextPosition='Hide'
Type='Items'>
<DropDownGallery.MenuLayout>
<FlowMenuLayout Columns='1' Rows='5' Gripper='None' />
</DropDownGallery.MenuLayout>
<DropDownGallery.MenuGroups>
<MenuGroup>
<Button CommandName='cmdCommandSpace' />
</MenuGroup>
</DropDownGallery.MenuGroups>
</DropDownGallery>
</Group>

</Tab>
</Ribbon.Tabs>
</Ribbon>
</Application.Views>
[/code]
В секции представлений мы задаём использование DropDownGallery с её разметкой (сколько столбцов и строк мы хотим) и командным пространством. Коллекцией элементов её делает задание атрибуту Type значения "Items". Более подробно об атрибутах DropDownGallery можно прочитать на MSDN.


Использование DropDownGallery — код
Создайте экземпляр вспомогательного класса RibbonLib.DropDownGallery и зарегистрируйте некоторые из его событий:

[code]private Ribbon _ribbon = new Ribbon();
private RibbonDropDownGallery _dropDownGallery;

public Form1()
{
InitializeComponent();

_dropDownGallery = new RibbonDropDownGallery(_ribbon, (uint)RibbonMarkupCommands.cmdDropDownGallery);

_dropDownGallery.OnExecute += new OnExecuteEventHandler(_dropDownGallery_OnExecute);
_dropDownGallery.OnPreview += new OnPreviewEventHandler(_dropDownGallery_OnPreview);
_dropDownGallery.OnCancelPreview += new OnCancelPreviewEventHandler(_dropDownGallery_OnCancelPreview);
}

void _dropDownGallery_OnCancelPreview(PropertyKeyRef key, PropVariantRef currentValue, IUISimplePropertySet commandExecutionProperties)
{
Console.WriteLine("DropDownGallery::OnCancelPreview");
}

void _dropDownGallery_OnPreview(PropertyKeyRef key, PropVariantRef currentValue, IUISimplePropertySet commandExecutionProperties)
{
Console.WriteLine("DropDownGallery::OnPreview");
}

void _dropDownGallery_OnExecute(PropertyKeyRef key, PropVariantRef currentValue, IUISimplePropertySet commandExecutionProperties)
{
Console.WriteLine("DropDownGallery::OnExecute");
}
[/code]
Добавьте элементы в DropDownGallery:

[code]private void Form1_Load(object sender, EventArgs e)
{
_ribbon.InitFramework(this);

FillDropDownGallery();
}

private void FillDropDownGallery()
{
// задаём метку
_dropDownGallery.Label = "Размер";

// задаём элементы _dropDownGallery
IUICollection itemsSource = _dropDownGallery.ItemsSource;
itemsSource.Clear();
foreach (Image image in imageListLines.Images)
{
itemsSource.Add(new GalleryItemPropertySet()
{
ItemImage = _ribbon.ConvertToUIImage((Bitmap)image)
});

}
}
[/code]
Обратите внимание, что здесь я использую стандартный элемент управления ImageList, чтобы хранить точечные рисунки для DropDownGallery. GalleryItemPropertySet — вспомогательный класс, который представляет отдельный элемент внутри коллекции элементов.


Использование SplitButtonGallery — разметка ленты
Теперь я покажу, как использовать SplitButtonGallery в качестве коллекции команд.

Секция команд:

[code]<Command Name='cmdGroupSplitButtonGallery' Id='1004' LabelTitle='Разделённая кнопка' />
<Command Name='cmdSplitButtonGallery' Id='1005' LabelTitle='Кисти' >
<Command.LargeImages>
<Image>Res/Brush1.bmp</Image>
</Command.LargeImages>
</Command>
[/code]
Секция представлений:

[code]…
<Group CommandName="cmdGroupSplitButtonGallery" SizeDefinition="OneButton">
<SplitButtonGallery CommandName="cmdSplitButtonGallery"
TextPosition="Hide" Type="Commands" HasLargeItems="true">
<SplitButtonGallery.MenuLayout>
<FlowMenuLayout Columns="4" Rows="3" Gripper="None"/>
</SplitButtonGallery.MenuLayout>
</SplitButtonGallery>
</Group>

[/code]
В секции представлений мы задаём использование SplitButtonGallery с её разметкой (сколько столбцов и строк мы хотим) и, в зависимости от желания, командным пространством. Коллекцией команд её делает задание атрибуту Type значения "Commands". Более подробно об атрибутах SplitButtonGallery можно прочитать на MSDN.


Использование SplitButtonGallery — код
Создайте экземпляр вспомогательного класса RibbonLib.SplitButtonGallery.

[code]private Ribbon _ribbon = new Ribbon();
private RibbonSplitButtonGallery _splitButtonGallery;
private RibbonButton[] _buttons;

public Form1()
{
InitializeComponent();

_splitButtonGallery = new RibbonSplitButtonGallery(_ribbon, (uint)RibbonMarkupCommands.cmdSplitButtonGallery);
}
[/code]
Добавьте элементы в SplitButtonGallery:

[code]private void Form1_Load(object sender, EventArgs e)
{
_ribbon.InitFramework(this);

FillSplitButtonGallery();
}

private void FillSplitButtonGallery()
{
// задаём метку
_splitButtonGallery.Label = "Кисти";

// готовим вспомогательные классы для команд
_buttons = new RibbonButton[imageListBrushes.Images.Count];
uint i;
for (i = 0; i < _buttons.Length; ++i)
{
_buttons = new RibbonButton(_ribbon, 2000 + i)
{
Label = "Метка " + i.ToString(),
LargeImage = _ribbon.ConvertToUIImage((Bitmap) imageListBrushes.Images[(int) i])
};
}

// задаём категории _splitButtonGallery
IUICollection categories = _splitButtonGallery.Categories;
categories.Clear();
categories.Add(new GalleryItemPropertySet() { Label = "Категория 1", CategoryID = 1 });

// задаём элементы _splitButtonGallery
IUICollection itemsSource = _splitButtonGallery.ItemsSource;
itemsSource.Clear();
i = 0;
foreach (Image image in imageListBrushes.Images)
{
itemsSource.Add(new GalleryCommandPropertySet()
{
CommandID = 2000 + i++,
CommandType = CommandType.Action,
CategoryID = 1
});
}

// добавляем элемент по умолчанию к коллекции элементов
itemsSource.Add(new GalleryCommandPropertySet()
{
CommandID = (uint)RibbonMarkupCommands.cmdSplitButtonGallery,
CommandType = CommandType.Action,
CategoryID = 1
});
}
[/code]
GalleryCommandPropertySet — вспомогательный класс, который представляет отдельный элемент внутри коллекции команд.

Важно: Если вы не добавите элемент по умолчанию в список элементов коллекции SplitButtonGallery, элементы будут появляться дважды! Вероятно, это баг.


Использование InRibbonGallery — разметка ленты
Теперь я покажу, как использовать InRibbonGallery в качестве коллекции элементов.

Секция команд:

[code]<Command Name='cmdGroupInRibbonGallery' Id='1006' LabelTitle='На ленте' />
<Command Name='cmdInRibbonGallery' Id='1007' />[/code]
Секция представлений:
[code]…
<Group CommandName="cmdGroupInRibbonGallery" SizeDefinition="OneInRibbonGallery">
<InRibbonGallery CommandName="cmdInRibbonGallery" Type="Items"
MaxRows="3" MaxColumns="7">
</InRibbonGallery>
</Group>
…[/code]
В секции представлений мы задаём использование InRibbonGallery с её разметкой. Обратите внимание, что InRibbonGallery предоставляет больше возможностей по размещению её элементов. Более подробно об атрибутах InRibbonGallery можно прочитать на MSDN.


Использование InRibbonGallery — код
Подобен коду для DropDownGallery. Это сообщение и так достаточно длинное (прим. переводчика: :) )


Новый механизм событий в Windows Ribbon for WinForms версии 2.5
Я только что выпустил очередное обновление для проекта.

Примечание: этот выпуск содержит серьёзные изменения, используйте его только в случае, если начинаете новый проект, или если вы не против внести необходимые обновления в код.

В основном я изменил то, как посылаются события в библиотеке, сделал этот процесс немного более дружественным для .NET.

Выгоды от этих изменений:

  • Теперь контролы генерируют события как отправители (sender) событий.
  • Например, это позволяет регистрировать одну и ту же функцию обратного вызова (callback function) на различные кнопки и при этом иметь возможность узнать, какая кнопка создала событие.
  • Теперь вы можете использовать библиотеку Windows Ribbon for WinForms в языках, которые умеют работать только с "правильными" обработчиками событий .NET. Первый запрос этой возможности был от человека, желавшего использовать библиотеку на Progress ABL… За пределами C#, C++ и VB.NET есть целый мир…



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

Прим. переводчика: Поскольку все статьи серии посвящены написанию приложений на языке C#, то здесь мы рассмотрим только обновление кода на C#. Инструкции по обновлению кода на Visual Basic .NET можно найти в оригинальном сообщении Арика.

Изменились названия и сигнатуры событий, соответственно, код, похожий на этот:

[code]_buttonNew.OnExecute += new OnExecuteEventHandler(_buttonNew_OnExecute);
_richFont.OnPreview += new OnPreviewEventHandler(_richFont_OnPreview);
_richFont.OnCancelPreview += new OnCancelPreviewEventHandler(_richFont_OnCancelPreview);[/code]
Нужно заменить кодом, похожим на этот:

[code]_buttonNew.ExecuteEvent += new EventHandler<ExecuteEventArgs>(_buttonNew_OnExecute);
_richFont.PreviewEvent += new EventHandler<ExecuteEventArgs>(_richFont_OnPreview);
_richFont.CancelPreviewEvent += new EventHandler<ExecuteEventArgs>(_richFont_OnCancelPreview);[/code]
И заменить сигнатуры методов, похожие на эту:

[code]void _buttonNew_OnExecute(PropertyKeyRef key, PropVariantRef currentValue, IUISimplePropertySet commandExecutionProperties)[/code]
Похожими на эту:

[code]void _buttonNew_OnExecute(object sender, ExecuteEventArgs e)[/code]
Заметьте, что класс ExecuteEventArgs содержит данные, которые были ранее напрямую переданы в метод Execute.


Заключение
На этом пока всё. Стоит сказать, что на момент написания статьи в файле "GalleryPropertiesProvider.cs" библиотеки Windows Ribbon for WinForms присутствовала ошибка, в результате которой в коллекцию DropDownGallery не добавлялись элементы из ImageList. Как только Арик исправит данный баг, я сообщу об этом в комментариях к статье, а пока советую воспользоваться файлом из сборки 45275.

В следующей статье мы рассмотрим сразу четыре элемента управления ленты: флажок (CheckBox), выключатель (ToggleButton), а также специфические контролы ленты DropDownColorPicker и FontControl.


Sgt.Riggs, TheVista.Ru Team,
Октябрь 2010

Комментарии

Не в сети

Риббоны - это хорошо. Но никогда не стесняйтесь делать самые необычные интерфейсы, иначе вы убьёте в себе дизайнера.

29.10.10 19:10
0
Не в сети

Исходные сообщения в блоге Арика Познански, переведённые в этой статье:

Windows Ribbon for WinForms, Part 11 – DropDownGallery, SplitButtonGallery and InRibbonGallery
Windows Ribbon for WinForms v2.5 Released – New Events Mechanism

29.10.10 21:29
0
Не в сети

Armanx64, в какой-то степени Вы, конечно, правы, но иногда эти самые необычные интерфейсы настолько режут глаз, что пользоваться программой становится просто противно. Это одна из причин, по которым я люблю продукты Майкрософт: в большинстве своём они выглядят приятно глазу, хотя исключения есть всегда. Насчёт дизайнера: во мне, например, никогда дизайнер не жил, но на мой взгляд, спроектировать вкладки, группы, разметку кнопок и в принципе выбрать подходящие контролы на ленте - дорогого стоит (ох, как же я намучился с разметкой ленты! ).

29.10.10 22:20
0
Не в сети

но иногда эти самые необычные интерфейсы настолько режут глаз, что пользоваться программой становится просто противно



Никто и не спорит, что косой интерфейс у многих быдлопрог, написанный на C++ в стиле "Ура, мы освоили GDI Canvas! Let's eye lift!", может вызвать чувство, что кто-то имеет жестокую неприязнь к людям.
Но можно делать хорошо - WPF и brain вам в руки. Стандартный интерфейс по гайдлайнам Win7 - приятно. Хороший оригинальный интерфейс на WPF/Silverlight - приятнее вдвойне.

29.10.10 22:34
0
Не в сети

Armanx64, абсолютно согласен. WPF/Silverlight в умелых руках творят чудеса У меня всё никак не дойдут руки до книжек по ним, да я и C#-то до сих пор толком не освоил по той же причине

29.10.10 22:43
0
Не в сети

Sgt.Riggs, всё точно также
Никак не дойдут руки.

30.10.10 15:58
0
Не в сети

Sgt.Riggs, а вот EverNote не смогли... Переписали Evernote v4 с C#/WPF на C++

31.10.10 07:26
0
Не в сети

alexbu, это их дело. При этом конкурирующий OneNote на WPF живёт и здравствует.
Могу предположить, что просто чёрный пиар. Или нормальных кодеров они не нашли.

31.10.10 08:28
0
Не в сети

alexbu, если я правильно понял, о чём идёт речь, то на сайте Evernote я вижу очень много различных платформ. Поэтому, возможно, переход был сделан для унификации кода и внешнего вида (не удивлюсь, что они перешли не на что-то, а на Qt4).

31.10.10 13:38
0
Не в сети

Почитал их блог. Теперь придерживаюсь того же мнения, что и Armanx64 Какие-то они... непрофессионалы.

31.10.10 13:43
0
Не в сети

Да уж. Похоже, что они решили сэкономить на .net-разработчиках. Да и жалобы на детские ошибки кодеров.

надежный C++


да уж, кто-кто, а C++ надёжен как 3,14здец в руках ребёнка...

31.10.10 16:11
0
Не в сети

Armanx64, C++ велик, но он куда как сложнее, нежели тот же C#, да и те же WPF, Silverlight и много чего другого на нём не реализовать, а значит, он уже достаточно устарел...

Для тех, кто разрабатывает приложения на WPF:

Нашёл реализацию Fluent Ribbon - это та лента, которая используется в Microsoft Office 2010, гораздо более функциональная, чем стандартный COM-объект Windows 7 Ribbon, который Арик и "обернул" (wrapper - "обёртка", если кто забыл) в своей библиотеке. Однако в данной реализации Fluent нет некоторых полезных функций, например, навигации по ленте с помощью клавиатуры, что невозбранно присутствует в нашем "обёрнутом" COM-объекте. В данный момент готовится выход версии 2 с очень интересными изменениями, поэтому тем, кто загорелся желанием использовать Fluent в своём WPF-приложении, советую взять этот проект на заметку и немного подождать.

31.10.10 23:53
0
Не в сети

C++ велик, но он куда как сложнее


Я не спорю. Это очень гибкий хлыст, настолько гибкий, что может запросто ударить вам по носу. В C# есть защита от дурака. В C++ же всё намного хуже...
Впрочем, на C# не напишешь драйвер, например.

01.11.10 09:43
0
Не в сети

Armanx64, почему же? По-моему, пишут что-то Я, кажется, даже книгу видел.

01.11.10 14:58
0
Не в сети

Кстати, ещё об Evernote. У них в блоге в причинах перехода с WPF на C++ указана такая вещь:

... мы столкнулись с рядом проблем, которые невозможно было легко исправить: размытый шрифт ...


Смешно сказать, но исправляется эта надуманная размытость одной-единственной строчкой в XAML-файле (правда, не могу сказать точно, появилась эта возможность в WPF 4 или раньше):

TextOptions.TextFormattingMode="Display"


Остальные "проблемы" - это вообще детский сад, нужно уметь писать код на используемом языке, а если не умеете, то и жаловаться нечего. Плохому танцору, как говорится, ноги мешают.

04.11.10 14:34
0
Для возможности комментировать войдите в 1 клик через

По теме

Акции MSFT
420.55 0.00
Акции торгуются с 17:30 до 00:00 по Москве
Все права принадлежат © ms insider @thevista.ru, 2022
Сайт является источником уникальной информации о семействе операционных систем Windows и других продуктах Microsoft. Перепечатка материалов возможна только с разрешения редакции.
Работает на WMS 2.34 (Страница создана за 0.045 секунд (Общее время SQL: 0.016 секунд - SQL запросов: 81 - Среднее время SQL: 0.0002 секунд))
Top.Mail.Ru