WPF 工具栏项 HorizontalAligment="Right"
Posted
技术标签:
【中文标题】WPF 工具栏项 HorizontalAligment="Right"【英文标题】:WPF Toolbar Items HorizontalAligment="Right" 【发布时间】:2011-01-13 04:30:01 【问题描述】:是否可以使 WPF 工具栏中的元素具有 Right 的 HorizontalAlignment?
<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>
我尝试将内部元素添加到网格中,并将ColumnDefinition
s 也分配给左/右。我也试过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 工具栏项 HorizontalAligment="Right"的主要内容,如果未能解决你的问题,请参考以下文章
安卓电视 |如何在父视图中居中 ListRow 项 (HorizontalGridView)
包装在 HorizontalScrollView 中的 Android Listview 高度不正确,其中列表项的高度不同
如何摆脱烦人的 HorizontalContentAlignment 绑定警告?