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

Можно ли сделать так, чтобы элементы на панели инструментов 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>

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

ОБНОВИТЬ:

<DockPanel LastChildFill="True">

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

8 ответов

Решение

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

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

<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"/>

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

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

<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. Первый имеет выравнивание по умолчанию (влево), второй выравнивается по правому краю. Это, кажется, делает трюк для меня.

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

<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, но я верю, что это будет работать и в предыдущих версиях.

    <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>

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

Помните, что с док-панелью последовательность, в которую вы помещаете предметы, очень важна.

НТН

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

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

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>

Если вы хотите всегда держать последнюю кнопку на панели инструментов, скажем кнопку помощи, которую вы всегда хотите видеть, добавьте атрибут ToolBar.OverflowMode="Never" к его элементу.

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

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

    <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"/>

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

Я не очень доволен решением "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>
Другие вопросы по тегам