Элемент управления ToolBar

80

Класс ToolBar в WPF обычно заполняется объектами Button, ComboBox, CheckBox, RadioButton и Separator. Поскольку все они (кроме Separator) являются элементами управления содержимым, внутри них можно размещать текстовое и графическое содержимое. Хотя допускается использовать и другие элементы, такие как Label и Image для добавления в ToolBar неинтерактивных элементов, эффект зачастую оказывается неоднозначным.

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

Например, кнопки в панели инструментов выглядят простыми и плоскими и не имеют ни границы, ни затененного фона. Поверхность панели инструментов проглядывает снизу, и при наведении на кнопку курсора мыши она подсвечивается голубым цветом.

С точки зрения WPF кнопка в панели инструментов практически ничем не отличается от кнопки в окне: обе представляют собой активизируемые щелчком области, которые разработчик может использовать для выполнения какого-нибудь действия. Разница состоит лишь в визуальном внешнем виде. Поэтому идеальное решение — воспользоваться существующим классом Button и либо настроить должным образом различные его свойства, либо изменить шаблон элемента управления. Именно это и сделано в классе ToolBar: в нем переопределен стиль, используемый по умолчанию для потомков некоторых типов, включая кнопки.

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

Класс ToolBar изменяет не только внешний вид многих из размещаемых в нем элементов управления, но также и поведение унаследованных от него классов ToggleButton, CheckBox и RadioButton. Элементы ToggleButton и CheckBox в ToolBar визуализируются как обычные кнопки, но при выполнении на них щелчка остаются выделенными (до тех пор, пока на них не будет снова совершен щелчок). RadioButton имеет похожий внешний вид, но снять выделение с этого элемента можно, только щелкнув на другом таком же элементе в группе. Во избежание путаницы группу объектов RadioButton в панели инструментов всегда лучше отделять с помощью Separator.

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

<Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="auto"></RowDefinition>
                    <RowDefinition></RowDefinition>
                </Grid.RowDefinitions>
                <ToolBar>
                    <Button>
                        <Image Source="open-sign.png" MaxHeight="32"></Image>
                    </Button>
                    <Separator></Separator>
                    <Button>New</Button>
                    <Button>Open</Button>
                    <Button>Close</Button>
                    <Separator></Separator>
                    <CheckBox FontWeight="Bold">Bold</CheckBox>
                    <CheckBox FontStyle="Italic">Italic</CheckBox>
                    <CheckBox>
                        <TextBlock TextDecorations="Underline">Underline</TextBlock>
                    </CheckBox>
                    <Separator></Separator>
                    <ComboBox SelectedIndex="1">
                        <ComboBoxItem>50%</ComboBoxItem>
                        <ComboBoxItem>100%</ComboBoxItem>
                        <ComboBoxItem>150%</ComboBoxItem>
                    </ComboBox>
                </ToolBar>
     </Grid>
Элемент управления ToolBar

В примере на рисунке кнопки содержат только текст, однако обычно кнопки в ToolBar включают графическое содержимое. Более того, текстовое и графическое содержимое также можно комбинировать упаковав элементы Image и TextBlock или Label в элемент StackPanel с горизонтальной ориентацией. В качестве графического содержимого могут использоваться растровые изображения (чреватые появлением при определенных разрешениях артефактов масштабирования), пиктограммы (чуть более лучший вариант из-за того, что позволяют предоставлять в одном файле несколько версий изображения с разными размерами) и векторные изображения (требующие написания наибольшего объема кода разметки, но обеспечивающие идеальный эффект при изменении размера).

С элементом управления ToolBar связано несколько странностей. В отличие от других элементов управления, унаследованных от ItemsControl, он не предоставляет отдельный класс-оболочку. Другими словами, класса вроде ToolBarItem не существует.

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

В ToolBar есть еще одно интересное свойство Orientation. Установив ToolBar.Orientation в Vertical, можно получить панель инструментов, располагаемую сверху вниз и пристыкованную к одной из сторон окна. Однако все элементы в этой панели все равно будут иметь горизонтальную ориентацию (например, текст не будет повернут соответствующим образом), если только для их переворачивания не применить трансформацию LayoutTransform.

Дополнительное меню

Если в панели инструментов находится больше содержимого, чем может уместиться в окне, лишние элементы удаляются и помещаются в дополнительное меню (overflow menu), которое можно увидеть, щелкнув на указывающей вниз стрелке в конце панели инструментов. На рисунке показана та же панель инструментов, что была на рисунке выше, но только в окне меньшего размера, что приводит к созданию дополнительного меню:

Дополнительное меню, создавамое автоматически

Элемент управления ToolBar добавляет элементы в дополнительное меню автоматически, начиная с конца (т.е. с последнего элемента). Однако это поведение можно настраивать, применяя к элементам в панели инструментов присоединенное свойство ToolBar.OverflowMode.

Значение OverflowMode.Never позволяет сделать так. чтобы элемент вообще никогда не размещался в дополнительном меню, OverflowMode.AsNeeded — так, чтобы элемент размещался в дополнительном меню только в случае нехватки места, а OverflowMode.Always — чтобы он всегда оставался в этом меню. (Например, в Visual Studio в дополнительном меню всегда размещается команда настройки Add or Remove Buttons (Добавить или удалить кнопки), а в Excel 2003 и Word 2003 — команды Show Buttons on Two Rows (Отображать кнопки на двух строках) и Show Buttons on One Row (Отображать кнопки на одной строке).)

В случае если контейнер панели инструментов (обычно окно) окажется меньше пространства, необходимого для отображения всех элементов OverflowMode.Always, не уместившиеся элементы будут усечены по краям контейнера и станут недоступными для пользователя.

Если в панели инструментов содержится более одного элемента OverflowMode.AsNeeded, тогда ToolBar сначала удаляет те элементы, что находятся в конце этой панели. К сожалению, возможности назначения элементам панели инструментов относительных приоритетов не существует. Например, нельзя создать элемент, допускающий размещение в дополнительном меню, но не помещаемый туда до тех пор, пока не будут перемещены все остальные передвигаемые элементы. Также нельзя создать кнопки, способные корректировать свои размеры в соответствии с количеством доступного пространства, вроде тех, что предлагаются в Office 2007. Для устранения этих пробелов следует искать элементы управления от независимых разработчиков.

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