WPF 工具栏项 Horizo​​ntalAligment="Right"

Posted

技术标签:

【中文标题】WPF 工具栏项 Horizo​​ntalAligment="Right"【英文标题】:WPF Toolbar Items HorizontalAligment="Right" 【发布时间】:2011-01-13 04:30:01 【问题描述】:

是否可以使 WPF 工具栏中的元素具有 Right 的 Horizo​​ntalAlignment?

<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 元素。

【问题讨论】:

【参考方案1】:

进一步的调查表明,为了做到这一点,我需要在ToolBar 内设置Grid 的宽度,或者将ToolBar 内的DockPanel 动态设置为ToolBar 的宽度Toolbar 的宽度使用RelativeSource

但是,这并不是一个干净的解决方案。让Toolbar 在调整大小时正确更新是相当复杂的。所以相反,我发现了一些 hack,看起来,并且通过添加外部 Grid 来操作更清晰

<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 的 Width 属性,我实际上觉得这是更清洁更有效的方法。

【讨论】:

实际上我发现这是一个绝妙(而且非常简洁)的解决方案。我被这个问题困扰了很久。谢谢! 这真是一个绝妙的主意。谢谢! 对长期存在的臀部疼痛的简单而出色的解决方案 :-) 这将导致您的右对齐项目(在您的情况下为 ComboBox)如果调整大小(由于窗口大小调整)到最右边的工具栏项目一直在的位置,则浮动在工具栏项目上向右。【参考方案2】:

对于寻找解决方案的其他人,以下方法对我有用:

<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,但我相信这也适用于以前的版本。

【讨论】:

【参考方案3】:

我意识到这是一个老话题,但在提问时它仍然会弹出。这就是我处理这个问题的方式:

<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 上。第一个具有默认(左)对齐,第二个是右对齐。它似乎对我有用。

【讨论】:

【参考方案4】:
    <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>

【讨论】:

您的答案有效,但如果在按钮 A 和 B 之间放置分隔符,则分隔符不会显示,但会保持其边距。知道为什么它不显示吗?【参考方案5】:

我就是这样做的:

我为工具栏创建了一个样式

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

这样,您的按钮将右对齐

【讨论】:

这行得通,但它很糟糕,因为我们完全替换了 ToolBar 的模板,因此失去了默认样式。【参考方案6】:

我对“WidthConverter”解决方案不是很满意,因为最后我得到了一些动态元素。进一步的搜索让我找到了here,这似乎对我来说是完美的。如果您有兴趣,这是我的代码示例:

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

【讨论】:

啊,这种方法在窗口调整大小时效果不佳。 这不起作用,因为如果您缩小窗口,所有工具栏按钮都会消失。否则,它会完美运行。因此,如果对这种方法进行微调以使其发挥作用,那就太好了。 好的,我在social.msdn.microsoft.com/Forums/en-US/wpf/thread/…(来自 dhbusch2)找到了另一个帖子,这对我来说真的很完美,除了我必须对按钮应用样式,例如 Style="StaticResource x:Static ToolBar .ButtonStyleKey"【参考方案7】:

我对此的解决方案是创建一个具有类似“弹簧”功能的标签控件,这样它就可以在工具栏上的按钮之间填充空白,从而“右对齐”工具栏的组合框(或任何其他控件)需要“右对齐”。

为此,我创建了一个 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();
    

然后,我在工具栏中添加了一个标签控件,放置在您需要右对齐的组合框的左侧。将标签的 Width 绑定到工具栏的 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" 属性添加到其元素。

【讨论】:

您的解决方案确实看起来更干净。但是,我不能让它为我工作。能否提供一个左侧一个按钮,右侧另一个按钮的工具栏的完整示例? 更新了答案以包含一个示例。第一个按钮将左对齐,第二个按钮将右对齐。您需要调整转换器参数以获得所需的结果。【参考方案8】:

您是否尝试过使用填充工具栏的 DockPanel,然后您可以将 ComboBox 停靠在右侧。

请记住,对于停靠面板,您放置项目的顺序非常重要。

HTH

【讨论】:

如何用 DockPanel 填充工具栏?我试过了,只能动态地做。除非有什么我不知道的,这是工具栏的问题。这就是为什么这对我不起作用。 现在工作太忙了,我会在这个周末发布一个解决方案,感觉应该会更干净一些。

以上是关于WPF 工具栏项 Horizo​​ntalAligment="Right"的主要内容,如果未能解决你的问题,请参考以下文章

安卓电视 |如何在父视图中居中 ListRow 项 (Horizo​​ntalGridView)

包装在 Horizo​​ntalScrollView 中的 Android Listview 高度不正确,其中列表项的高度不同

将按钮控件链接到数据 (WPF)

如何摆脱烦人的 Horizo​​ntalContentAlignment 绑定警告?

Horizo​​ntalAlignment=Stretch、MaxWidth 和 Left 同时对齐?

WPF 按钮中的文本内容未垂直居中