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

27.08.2010 12:50 | deeper2k

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

Сегодня мы рассмотрим ещё несколько элементов управления ленты, как-то: вкладки (Tabs) с группами (Groups), кнопка справки (HelpButton), счётчик (Spinner) и раскрывающийся (или выпадающий) список (ComboBox).

Итак, приступим.


Вкладки, группы и кнопка справки
Результатом данной части статьи будет очередное приложение-образец с именем "04-TabGroupHelp". Выглядит оно следующим образом:



Кнопки, кнопки, кнопки
Так что же есть вкладки? Это всего лишь контейнеры для других элементов управления. В этом примере мы будем использовать только кнопки. Я рассмотрю другие типы контролов в следующих статьях.

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

Что такое кнопка справки? Ещё одна кнопка. Из некоторых соображений у неё есть своё особое место и заранее заданный значок (см. на правую сторону изображения).

Использование вкладок и групп
Секция команд разметки ленты остаётся всё той же — просто список элементов, сопоставляющих обозначения, используемые программистом, и идентификаторы, используемые фреймворком ленты. А также некоторые строковые ресурсы и точечные рисунки.

Как всегда, всё интересное находится в секции представлений разметки:

<Application.Views>
  <Ribbon>
    <Ribbon.Tabs>
      <Tab CommandName="cmdTabMain">
        <!-- страшная часть -->
        <Tab.ScalingPolicy>
          <ScalingPolicy>
            <ScalingPolicy.IdealSizes>
              <Scale Group="cmdGroupFileActions" Size="Large" />
              <Scale Group="cmdGroupExit" Size="Large" />
            </ScalingPolicy.IdealSizes>
            <Scale Group="cmdGroupFileActions" Size="Medium" />
          </ScalingPolicy>
        </Tab.ScalingPolicy>
        <!-- полезная часть -->
        <Group CommandName="cmdGroupFileActions" SizeDefinition="ThreeButtons">
          <Button CommandName="cmdButtonNew" />
          <Button CommandName="cmdButtonOpen" />
          <Button CommandName="cmdButtonSave" />
        </Group>
        <Group CommandName="cmdGroupExit" SizeDefinition="OneButton">
          <Button CommandName="cmdButtonExit" />
        </Group>
      </Tab>
      <Tab CommandName ="cmdTabDrop">
        <Group CommandName="cmdGroupDrop" SizeDefinition="ThreeButtons">
          <Button CommandName="cmdButtonDropA" />
          <Button CommandName="cmdButtonDropB" />
          <Button CommandName="cmdButtonDropC" />
        </Group>
      </Tab>
    </Ribbon.Tabs>
  </Ribbon>
</Application.Views>

iews>[/code]
В этой разметке я назначил две вкладки. На первой вкладке расположены две группы, на второй — одна. Я обозначил важные части разметки первой вкладки. К сожалению, в силу особенностей определения схемы (англ. schema definition — прим. переводчика) ленты, "страшная" часть должна располагаться перед "полезной".

"Полезная" часть:
Всего лишь простое назначение групп на вкладке и элементов управления внутри каждой группы. Единственная интересная вещь — это атрибут SizeDefinition в тэге Group. Это определение расположения контролов в группе. Вы можете описать собственные варианты расположения или использовать уже имеющиеся, которых обычно бывает вполне достаточно. Полный список (с удобными иллюстрациями) можно посмотреть в статье "Настройка ленты с помощью определений размеров (англ. Size Definitions — прим. переводчика) и политик масштабирования (англ. Scaling Policies — прим. переводчика)" на MSDN.

"Страшная" часть:
Чтобы понять эту часть, нужно знать, что одной из функций фреймворка ленты является возможность перераспределения ваших контролов на ленте в соответствии с имеющимся пространством. В основном лента обрабатывает это автоматически, но ей необходимо дать "подсказку", как следует распределять элементы, когда форма приложения становится всё меньше и меньше. Поэтому в "страшной" части мы сначала задаём идеальный размер для каждой группы. Размер может принимать одно из четырёх значений: Large (большой), Medium (средний), Small (маленький) и Popup (всплывающий). "Popup" означает, что вся группа должна сжиматься в один значок и "всплывать" при щелчке по нему.

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

Код для работы с этими кнопками такой же, как в предыдущей статье. Просто обрабатывайте событие OnExecute соответствующих кнопок.

Использование кнопки справки
Чтобы использовать кнопку справки, просто добавьте следующие строки в секцию представлений разметки ленты:

[code]<Application.Views>
<Ribbon>
<Ribbon.HelpButton>
<HelpButton CommandName="cmdHelp" />
</Ribbon.HelpButton>
<Ribbon.Tabs>
...
</Ribbon.Tabs>
</Ribbon>
</Application.Views>[/code]
Элемент управления "счётчик"
Элемент управления "счётчик" (Spinner) — контрол, который содержит десятичное значение (как тип double, только с более высоким разрешением). Элемент состоит из поля для редактирования и двух кнопок, для увеличения и уменьшения. Давайте попробуем его в действии:



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

Свойства счётчика, относящиеся к его значению

  • Decimal Value — Текущее десятичное значение счётчика.
    Идентификатор свойства: UI_PKEY_DecimalValue
  • Increment — Размер шага при нажатии на кнопки увеличения / уменьшения значения.
    Идентификатор свойства: UI_PKEY_Increment
  • Max Value — Максимальное значение, которое можно задать на счётчике.
    Идентификатор свойства: UI_PKEY_MaxValue
  • Min Value — Минимальное значение, которое можно задать на счётчике.
    Идентификатор свойства: UI_PKEY_MinValue


Замечание: Когда вы используете десятичные значения в Ribbon Framework, вы должны также использовать реализацию PropVariant, поддерживающую десятичные значения. Подробней об этом написано здесь: Задание десятичных значений в PropVariant.

Свойства счётчика, относящиеся к его оформлению

  • Decimal Places — Количество цифр после запятой.
    Идентификатор свойства: UI_PKEY_DecimalPlaces
  • Format String — Единицы измерения значения. На предыдущем изображении это "м" — метры.
    Идентификатор свойства: UI_PKEY_FormatString
  • Representative String — Строка, представляющая общее значение для счётчика. Используется для вычисления ширины счётчика, поэтому следует задавать здесь самую длинную строку, которая будет выводиться. Заметьте, что это не обязательно должно быть действительное значение, можно задать что-нибудь вроде: "XXXXXXXX".
    Идентификатор свойства: UI_PKEY_RepresentativeString


Общие параметры оформления

  • Keytip — Клавиатурный ускоритель ("горячая клавиша") для данной команды в фреймворке ленты (показывается при нажатии ALT в приложении с лентой).
    Идентификатор свойства: UI_PKEY_Keytip
  • Label — Метка для данной команды. Обычно появляется рядом с назначенным элементом управления.
    Идентификатор свойства: UI_PKEY_Label
  • Tooltip Title — Заголовок всплывающей подсказки для данной команды.
    Идентификатор свойства: UI_PKEY_TooltipTitle
  • Tooltip Description — Текст всплывающей подсказки для данной команды.
    Идентификатор свойства: UI_PKEY_TooltipDescription
  • Enabled — Флаг, показывающий, включён данный элемент управления или нет.
    Идентификатор свойства: UI_PKEY_Enabled


Свойства изображений

  • Large Image — Большое изображение для данной команды.
    Идентификатор свойства: UI_PKEY_LargeImage
  • Small Image — Маленькое изображение для данной команды.
    Идентификатор свойства: UI_PKEY_SmallImage
  • Large High Contrast Image — Большое изображение с высоким контрастом для данной команды.
    Идентификатор свойства: UI_PKEY_LargeHighContrastImage
  • Small High Contrast Image — Маленькое изображение с высоким контрастом для данной команды.
    Идентификатор свойства: UI_PKEY_SmallHighContrastImage


Использование счётчика — разметка ленты
Как всегда, команда должна быть определена:

[code]<Command Name="cmdSpinner"
Id="1018"
LabelTitle="Мой счётчик">
</Command>[/code]
Секция представлений тоже простая:

[code]<Application.Views>
<Ribbon>
<Ribbon.Tabs>
<Tab>
<Group>
<Spinner CommandName="cmdSpinner" />
</Group>
</Tab>
</Ribbon.Tabs>
</Ribbon>
</Application.Views>[/code]
Использование счётчика — код
Чтобы помочь нам управлять счётчиком, я создал вспомогательный класс, в котором выполняется вся работа, затрагивающая фреймворк ленты. Чтобы использовать его, создайте экземпляр RibbonSpinner, передав конструктору ссылку на экземпляр класса Ribbon и ID команды счётчика:

[code]private Ribbon _ribbon;
private RibbonSpinner _spinner;

public Form1()
{
InitializeComponent();

_ribbon = new Ribbon();
_spinner = new RibbonSpinner(_ribbon, (uint)RibbonMarkupCommands.cmdSpinner);
}[/code]
Теперь вы можете легко управлять свойствами счётчика, задавая их для экземпляра _spinner, например:

[code]private void InitSpinner()
{
_spinner.DecimalPlaces = 2;
_spinner.DecimalValue = 1.8M;
_spinner.TooltipTitle = "Высота";
_spinner.TooltipDescription = "Введите высоту в метрах.";
_spinner.MaxValue = 2.5M;
_spinner.MinValue = 0;
_spinner.Increment = 0.01M;
_spinner.FormatString = " м";
_spinner.RepresentativeString = "2.50 м";
_spinner.Label = "Высота:";
}[/code]
Использование элемента управления "счётчик" показано в приложении-образце "05-Spinner".

От переводчика: в заключении статьи смотрите очень важное замечание касательно счётчика.

Элемент управления "выпадающий список"
Элемент управления "выпадающий (или раскрывающийся) список" (ComboBox) ленты — по сути обычный контрол ComboBox, который мы все любим, но с дополнительной возможностью разделения элементов по категориям. Категория не является элементом и не может быть выбрана из списка. Она используется только для упорядочения элементов.



Свойства выпадающего списка, относящиеся к его значению

  • Items Source — Список элементов ComboBox. Он реализует интерфейс IUICollection, каждый элемент которого относится к типу: IUISimplePropertySet. Об этом будет рассказано чуть позже.
    Идентификатор свойства: UI_PKEY_ItemsSource
  • Categories — Список категорий. Также реализует IUICollection элементов IUISimplePropertySet.
    Идентификатор свойства: UI_PKEY_Categories
  • Selected Item — Индекс выбранного элемента в выпадающем списке. Если ничего не выбрано, возвращает UI_Collection_InvalidIndex, то есть, грубо говоря, -1.
    Идентификатор свойства: UI_PKEY_SelectedItem
  • String Value — Текущая строка в ComboBox. Это может быть строка, не являющаяся одним из элементов выпадающего списка, если его свойству IsEditable присвоено значение "true".
    Идентификатор свойства: UI_PKEY_StringValue



Свойства выпадающего списка, относящиеся к его оформлению

  • Representative String — Строка, представляющая общее значение для ComboBox. Используется для вычисления ширины выпадающего списка, поэтому следует задавать здесь самую длинную строку, которая будет выводиться. Заметьте, что это не обязательно должно быть действительное значение, можно задать что-нибудь вроде: "XXXXXXXX".
    Идентификатор свойства: UI_PKEY_RepresentativeString


Использование выпадающего списка — разметка ленты
Как всегда, команда должна быть определена:

[code]<Command Name="cmdComboBox2" Id="1019" />[/code]

Секция представлений:

[code]<Application.Views>
<Ribbon>
<Ribbon.Tabs>
<Tab>
<Group>
<ComboBox CommandName="cmdComboBox2"
IsAutoCompleteEnabled="true"
IsEditable="true"
ResizeType="VerticalResize" />
</Group>
</Tab>
</Ribbon.Tabs>
</Ribbon>
</Application.Views>[/code]
Атрибуты ComboBox:

  • CommandName — Имя команды, привязанной к данному выпадающему списку.
  • IsAutoCompleteEnabled — Флаг, показывающий, дополнять ли слова, когда вы пишете.
  • IsEditable — Флаг, показывающий, возможно ли свободное редактирование текста в ComboBox.
  • ResizeType — Возможность изменения размера ComboBox. Может принимать значения NoResize или VerticalResize.


Использование выпадающего списка — код
По аналогии с элементом управления "счётчик", я создал вспомогательный класс для взаимодействия между выпадающим списком и фреймворком ленты. Чтобы использовать ComboBox, создайте экземпляр RibbonComboBox, передав конструктору ссылку на экземпляр класса Ribbon и ID команды списка:

[code]private Ribbon _ribbon;
private RibbonComboBox _comboBox2;

public Form1()
{
InitializeComponent();

_ribbon = new Ribbon();
_comboBox2 = new RibbonComboBox(_ribbon, (uint)RibbonMarkupCommands.cmdComboBox2);
_comboBox2.RepresentativeString = "XXXXXXXXXXX";
}[/code]
Замечание: Мы задаём свойство RepresentativeString ПЕРЕД инициализацией фреймворка ленты. Это делается в силу того, что по некоторым причинам фреймворк считывает это свойство только однажды, когда лента инициализируется. Это означает, что, если вы измените его после инициализации, результата не будет, поскольку фреймворк его более не считывает. Кстати говоря, согласно текущей документации фреймворка ленты, это свойство не является частью ComboBox, но, как упоминалось ранее, оно контролирует ширину выпадающего списка.

В следующем куске кода показано, как использовать другой вспомогательный класс, называющийся GalleryItemPropertySet. Этот класс предоставляет контейнер для свойств отдельного элемента в IUICollection.

Добавление категорий и элементов в выпадающий список производится таким образом:

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

// задаём метку combobox2
_comboBox2.Label = "Расширенный список";

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

// задаём элементы _comboBox2
IUICollection itemsSource2 = _comboBox2.ItemsSource;
itemsSource2.Clear();
itemsSource2.Add(new GalleryItemPropertySet() { Label="Метка 1", CategoryID=1 });
itemsSource2.Add(new GalleryItemPropertySet() { Label="Метка 2", CategoryID=1 });
itemsSource2.Add(new GalleryItemPropertySet() { Label="Метка 3", CategoryID=2 });
}[/code]
Замечание: Добавление элементов и категорий возможно только ПОСЛЕ того, как фреймворк ленты был инициализирован.

События IUICollection
Объекты, реализующие интерфейс IUICollection, обычно посылают событие OnChanged, вызываемое в случае, если коллекция была изменена: вставкой элемента, удалением элемента, заменой элемента, сбросом коллекции.

Это событие посылается с помощью стандартного механизма событий COM, а именно: IConnectionPointContainer, IConnectionPoint и Advise().

Чтобы помочь пользователю обойти все эти вещи, я создал класс UICollectionChangedEvent, который привязывается к соответствующему интерфейсу IUICollection и посылает событие OnChanged как обычное .NET-событие.

Ниже приведён пример его использования:

[code]private RegisterEvent()
{
_uiCollectionChangedEvent = new UICollectionChangedEvent();
_uiCollectionChangedEvent.Attach(_comboBox1.ItemsSource);
_uiCollectionChangedEvent.OnChanged +=
new UICollectionChangedEvent.OnChangedEventHandler(_ChangedEvent_OnChanged);
}
[/code]
[code]void _ChangedEvent_OnChanged(UI_CollectionChange action,
uint oldIndex, object oldItem,
uint newIndex, object newItem)
{
MessageBox.Show("Получено событие OnChanged. Действие = " + action.ToString());
}[/code]
Замечание: Для ComboBox события OnChanged нет. Только для интерфейса IUICollection, который полностью отличается от контрола. Сам выпадающий список имеет 3 события, Execute, Preview и CancelPreview. Событие Execute можно использовать как событие "изменения выбора". Об этом будет рассказано в будущих статьях.

Использование элемента управления "выпадающий список" показано в приложении-образце "06-ComboBox".


Заключение
Имеется крайне важное замечание, касающееся элемента управления "счётчик" (Spinner). Один из пользователей обнаружил ошибку во враппере Арика Познански. Заключается она в следующем: значение счётчика задаётся в коде приложения, затем во время работы приложения пользователь меняет его через сам счётчик на ленте, и при сворачивании и последующем разворачивании приложения значение счётчика возвращается к заданному в коде.

Арик довольно оперативно отреагировал на сообщение об ошибке и исправил её. Вы можете либо целиком скачать новую сборку, либо вручную отредактировать код имеющейся у вас версии. Чтобы увидеть изменения в новой сборке (в данном случае они затронули лишь один файл — SpinnerPropertiesProvider.cs), нажмите ссылку "view diff" рядом с именем изменённого файла. В следующую версию библиотеки Windows Ribbon for WinForms (на момент написания статьи текущей являлась версия 2.4) Арик обещает включить это исправление.

Также хотелось бы упомянуть COM-структуру PropVariant, о которой было сказано в замечании к свойствам элемента управления "счётчик". Её подходящая реализация уже включена Ариком в проект его библиотеки, поэтому беспокоиться об этом не стоит.

На этом пока всё.

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


Sgt.Riggs, TheVista.Ru Team,
Август 2010

Комментарии

Не в сети

Хорошая статья. Только не могу понять почему в VS до сих пор нет стандартного визуального компонента что-бы просто взять и перетянуть.

27.08.10 14:32
0
Не в сети

Sm1le, есть, но он предназначен для MFC-приложений. Читайте первую статью из цикла ;)

27.08.10 17:12
0
Не в сети

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

Windows Ribbon for WinForms, Part 6 – Tabs, Groups and HelpButton
Windows Ribbon for WinForms, Part 7 – Spinner
Windows Ribbon for WinForms, Part 8 – ComboBox

27.08.10 17:18
0
Не в сети

Sgt.Riggs , mfc это хорошо, но я с++ давно забросил, так что надеюсь когда нибудь компонент появится)

27.08.10 17:25
0
Не в сети

Sm1le, может и появится, но пока нет. А нынешний Windows Ribbon - это COM-элемент, так что в идеале им управлять надо нативными функциями, то бишь нужен C++. Потому Арик свой враппер и написал, который, кстати, прекрасно работает, а Арик очень оперативно реагирует на сообщения о возможных ошибках, если их кто-то находит (сам с ним по поводу одной недоработки общался зимой, очень приятный в общении человек, кстати). А если учесть, что он сотрудник Microsoft Israel... В общем, по сути этот враппер и есть официальная реализация Ribbon для .NET Один минус - отсутствие визуального редактора ленты. Я задолбался в своём приложении писать разметку :-D Но в не-MFC-шных C++-приложениях всё то же самое, так что... Ну и кроме того, есть сторонние визуальные редакторы ленты, создающие полный код разметки.

27.08.10 17:51
0
Не в сети

Кстати, не так давно вышел финальный Ribbon для WPF: Download , Docs

30.08.10 11:53
0
Не в сети

SVRC, отлично, спасибо, что сообщили! Коллекция лент пополнилась ещё одной реализацией.

30.08.10 16:39
0
Для возможности комментировать войдите в 1 клик через

По теме

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