Элементы панели инструментов WPF HorizontalAligment = Right

Можно ли сделать так, чтобы элементы на панели инструментов WPF имели горизонтальное выравнивание по правому краю?

<ToolBar Height="38" VerticalAlignment="Top" Grid.Row="1">
    <Button HorizontalAlignment="Left" Width="50" VerticalAlignment="Stretch"/>
    <Button HorizontalAlignment="Left" Width="50" VerticalAlignment="Stretch"/>
    <ComboBox Width="120" HorizontalAlignment="Right"/>
</ToolBar>

Я пробовал добавлять элементы внутри в сетку и также назначать ColumnDefinitions влево / вправо. Я также пробовал StackPanel. Независимо от того, что я пытаюсь, мне кажется, что ComboBox не может быть «закреплен» на правой стороне панели инструментов.

ОБНОВЛЕНИЕ:

<DockPanel LastChildFill="True">

Не работает, он не заполняет элемент ToolBar, как обычный элемент.


person jsmith    schedule 04.02.2010    source источник


Ответы (8)


Дальнейшее расследование показало, что для этого мне нужно установить ширину Grid в ToolBar, или как сказал Крис Никол, , DockPanel внутри ToolBar динамически до ширины Toolbar с использованием RelativeSource.

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

<Grid>
    <ToolBar Height="38" VerticalAlignment="Top" Grid.Row="1">
        <Button HorizontalAlignment="Left" Width="50" VerticalAlignment="Stretch"/>
        <Button HorizontalAlignment="Left" Width="50" VerticalAlignment="Stretch"/>
    </ToolBar>
    
    <ComboBox Margin="0,0,15,0" Width="120" HorizontalAlignment="Right" Grid.Row="1"/>
</Grid>

Поскольку все мои элементы находятся в сетке, я могу разместить свой ComboBox поверх ToolBar, назначив его Grid.Row той же строке, что и панель инструментов. После того, как мой Margins слегка подтянул ComboBox, чтобы не мешать внешнему виду, он работает по мере необходимости, без ошибок. Поскольку единственный другой способ, который я нашел для этого, - это динамическая установка свойства DockPanel / Grid's Width, я действительно чувствую, что это более чистый и эффективный способ сделать это.

person jsmith    schedule 04.02.2010
comment
На самом деле я считаю это прекрасным (и очень изящным) решением. Меня так долго мучает эта проблема. Спасибо! - person Weipeng L; 22.07.2010
comment
Это действительно блестящая идея. Спасибо! - person newman; 11.11.2012
comment
Простое и блестящее решение давней боли в крупе :-) - person gchq; 03.10.2015
comment
Это приведет к тому, что ваш выровненный по правому краю элемент (в вашем случае ComboBox) будет плавать над элементами панели инструментов, если он будет изменен (из-за изменения размера окна) до точки, где крайний правый элемент панели инструментов находится полностью вправо. - person Dean Kuga; 28.06.2018

Я понимаю, что это старая тема, но она все равно всплывает, когда задаешь вопрос. Вот как я отвечаю на этот вопрос:

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition x:Name="MenuRow"    Height="25"/>
        <RowDefinition x:Name="ToolbarRow" Height="25"/>
        <RowDefinition x:Name="CatalogRow" Height="*"/>
        <RowDefinition x:Name="RecipeRow"  Height="0.4*"/>
    </Grid.RowDefinitions>
    <ToolBar Grid.Row="1">
        <Button x:Name="tbFileOpen" Margin="0,0,0,0" Click="MenuItem_Click"><Image Source="Icons/Main/File/Load.png"/></Button>
        <Button x:Name="tbFileSave" Margin="0,0,0,0" Click="MenuItem_Click"><Image Source="Icons/Main/File/Save.png"/></Button>
        <Button x:Name="tbFileClear" Margin="0,0,0,0" Click="MenuItem_Click"><Image Source="Icons/Main/File/New document.png"/></Button>
    </ToolBar>
    <ToolBar Grid.Row="1" HorizontalAlignment="Right">
        <Button x:Name="tbFileExit" Margin="0,0,0,0" Click="MenuItem_Click"><Image Source="Icons/Main/File/Exit.png"/></Button>
    </ToolBar>
</Grid>

Фактически: я создаю два объекта панели инструментов и размещаю их в одной строке Grid.row. Первый имеет выравнивание по умолчанию (по левому краю), второй - по правому краю. Кажется, это помогает мне.

person Leo Prast    schedule 04.01.2016

Для всех, кто ищет решение, у меня сработало следующее:

<ToolBar HorizontalAlignment="Stretch" ToolBarTray.IsLocked="True">
  <ToolBar.Resources>
    <Style TargetType="{x:Type DockPanel}">
      <Setter Property="HorizontalAlignment" Value="Right" />
    </Style>
</ToolBar.Resources>

Я использую .NET 4.6 и VS2015, но считаю, что это будет работать и в предыдущих версиях.

person dotNET    schedule 06.01.2016

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

Помните, что для док-панели очень важна последовательность, в которой вы размещаете элементы.

HTH

person Chris Nicol    schedule 04.02.2010
comment
Как бы вы заполнили панель инструментов DockPanel? Я пробовал и могу делать это только динамически .. Если я не знаю чего-то, это проблема ToolBar. Поэтому у меня это не сработает. - person jsmith; 05.02.2010
comment
просто сейчас очень занят работой, на этих выходных я опубликую решение, которое должно быть немного чище. - person Chris Nicol; 05.02.2010

    <ToolBar Width="100" VerticalAlignment="Top" >
        <ToolBar.Resources>
            <Style TargetType="{x:Type ToolBarPanel}">
                <Setter Property="Orientation" Value="Vertical"/>
            </Style>
        </ToolBar.Resources>

        <DockPanel>
            <ToolBarPanel Orientation="Horizontal" >
                <Button>A</Button>
                <Button>B</Button>
            </ToolBarPanel>
            <Button DockPanel.Dock="Right" HorizontalAlignment="Right">C</Button>
        </DockPanel>
    </ToolBar>

person Mark Cidade    schedule 22.01.2014
comment
Ваш ответ работает, но если поместить разделитель между кнопками A и B, разделитель не отображается, но сохраняет поле. Есть идеи, почему это не отображается? - person Somanna; 05.12.2020

Мое решение состояло в том, чтобы создать элемент управления меткой с «пружинной» способностью, чтобы он заполнял пустое пространство между кнопками на панели инструментов, таким образом «выравнивая по правому краю» поле со списком панели инструментов (или любой другой элемент управления, который требует » по правому краю).

Для этого я создал WidthConverter, который принимает фактическую ширину элемента управления ToolBar, а затем вычитает пространство, необходимое для выравнивания поля со списком по правому краю .:

public class WidthConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return Math.Max(System.Convert.ToDouble(value) - System.Convert.ToDouble(parameter), 0.0);
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

Затем я добавил на панель инструментов элемент управления меткой, расположенный слева от поля со списком, которое необходимо выровнять по правому краю. Свяжите ширину метки с ActualWidth панели инструментов и примените WidthConverter:

<Label Width="{Binding Converter={StaticResource WidthConverter}, ElementName=toolBar1, Path=ActualWidth, ConverterParameter=50}" />

Вам нужно будет настроить ConverterParameter в соответствии с вашими конкретными потребностями, пока вы не получите желаемое «правильное выравнивание». Более высокое число обеспечивает больше места для поля со списком, тогда как меньшее число обеспечивает меньше места.

Используя это решение, размер метки будет автоматически изменяться при изменении размера панели инструментов, создавая впечатление, что вы выровняли поле со списком по правому краю.

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

Используемый XAML:

<ToolBarPanel>
    <ToolBar Name="toolBar1">
        <Button>
            <Image Source="save.png"/>
        </Button>
    <Label Width="{Binding Converter={StaticResource Converters.WidthConverter},
                  ElementName=toolBar1,
                  Path=ActualWidth,
                  ConverterParameter=231}" HorizontalAlignment="Stretch" ToolBar.OverflowMode="Never"/>
    <Button>
        <Image Source="open.png"/>
    </Button>
</ToolBar>

If you desire to always keep the last button on the toolbar, say a help button that you always want visible, add the attribute ToolBar.OverflowMode="Never" to its element.

person Nathan Dace    schedule 15.05.2011
comment
Ваше решение кажется более чистым. Однако я не могу заставить его работать на меня. Можете ли вы предоставить полный образец панели инструментов, где одна кнопка находится слева, а другая - справа? - person newman; 08.06.2011
comment
Обновлен ответ, чтобы включить пример. Первая кнопка будет выровнена по левому краю, а вторая кнопка - по правому краю. Вам нужно будет настроить параметр конвертера, чтобы получить желаемый результат. - person Nathan Dace; 15.06.2011

Вот как я это сделал:

Я создал стиль для панели инструментов

    <Style x:Key="{x:Type ToolBar}" TargetType="{x:Type ToolBar}">
    <Setter Property="SnapsToDevicePixels" Value="true" />
    <Setter Property="OverridesDefaultStyle" Value="true" />
    <Setter Property="HorizontalAlignment" Value="Stretch"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ToolBar}">
                <Grid Background="{StaticResource ToolGridBackground}">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto"/>
                        <ColumnDefinition Width="*"/>
                        <ColumnDefinition Width="Auto"/>
                    </Grid.ColumnDefinitions>
                    <Image Grid.Column="0" Style="{StaticResource LogoImage}"/>
                    <ToolBarPanel Grid.Column="2" x:Name="PART_ToolBarPanel" IsItemsHost="true" Margin="0,1,2,2" Orientation="Horizontal"/>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Важная часть:

<Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto"/>
                        <ColumnDefinition Width="*"/>
                        <ColumnDefinition Width="Auto"/>
                    </Grid.ColumnDefinitions>

И

<ToolBarPanel Grid.Column="2"/>

При этом ваши кнопки будут выровнены по правому краю

person Daniel    schedule 24.02.2013
comment
Это работает, но это плохо, потому что мы полностью заменяем шаблон ToolBar и, таким образом, теряем стиль по умолчанию. - person diimdeep; 17.06.2013

Я не очень доволен решением "WidthConverter", потому что в конце у меня есть некоторые динамические элементы. Дальнейший поиск привел меня к здесь, который, кажется, работает идеально для меня. Вот мой пример кода на случай, если вам интересно:

<ToolBar Name="toolBar">
    <DockPanel Width="{Binding Path=ActualWidth, RelativeSource={RelativeSource AncestorType={x:Type ToolBarPanel}}}">
        <DockPanel.Resources>
            <Style TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Static ToolBar.ButtonStyleKey}}"></Style>
        </DockPanel.Resources>
        <Button x:Name="btnRefresh" ToolTip="Refresh" Click="btnRefresh_Click">
            <Image Margin="2 0" Source="/Resources/refresh.ico" Height="16" Width="16"/>
        </Button>
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
            <Image Margin="2 0" Source="/Resources/Help.ico" Height="16" Width="16"/>
            <TextBlock Text="Help" Margin="2 0" VerticalAlignment="Center"/>
        </StackPanel>
    </DockPanel>
</ToolBar>
person newman    schedule 25.05.2012
comment
Ах, этот подход не работает идеально при изменении размера окна. - person newman; 03.11.2012
comment
Это не работает, потому что все кнопки панели инструментов исчезают, если вы уменьшите окно. В остальном работает отлично. Так что было бы здорово, если бы в этот подход была внесена небольшая поправка, чтобы заставить его работать. - person newman; 07.05.2013
comment
Хорошо, я нашел еще одно сообщение по адресу social.msdn.microsoft.com/Forums/en-US/wpf/thread/ (от dhbusch2), который действительно идеально подходит для меня, за исключением того, что мне нужно применить стиль к кнопке, например Style = {StaticResource { x: Static ToolBar.ButtonStyleKey}} - person newman; 07.05.2013