我有一个如下所示的 WPF 上下文菜单:
<ContextMenu Width="300">
<MenuItem Command="{Binding MainWindowViewModel.NewCommand}">
<MenuItem.Icon>
<Image Source="pack://application:,,,/EAV.UI;component/Resources/Icons/MenuNew.png" Width="32" Height="32"/>
</MenuItem.Icon>
<MenuItem.HeaderTemplate>
<DataTemplate>
<TextBlock Text="New" HorizontalAlignment="Left" VerticalAlignment="Center"/>
</DataTemplate>
</MenuItem.HeaderTemplate>
</MenuItem>
</ContextMenu>
问题是图标重叠了图标列,像这样:
如何增加菜单图标列的宽度,使大图标在列中居中?
最佳答案
这只是一个解决方法,但它适用于 MenuItem 列的每个宽度。
结果会从此改变
为此
菜单中的所有内容都是动态构建的,除了菜单的图标“列”
使用 Snoop 我们可以看到它实际上是由三个 Rectangle 组成的
第一个矩形的宽度为 28
第二个矩形的宽度为 1,边距为 (29, 2, 0, 2)
第三个矩形的宽度为 1,边距为 (30, 2, 0, 2)
我通过为最宽的菜单图标添加一个 Loaded 事件来解决这个问题。
<ContextMenu Width="300">
<MenuItem Command="{Binding MainWindowViewModel.NewCommand}">
<MenuItem.Icon>
<Image Source="pack://application:,,,/EAV.UI;component/Resources/Icons/MenuNew.png"
Width="32"
Height="32"
Loaded="WidestImage_Loaded"/>
</MenuItem.Icon>
<MenuItem.HeaderTemplate>
<DataTemplate>
<TextBlock Text="New" HorizontalAlignment="Left" VerticalAlignment="Center"/>
</DataTemplate>
</MenuItem.HeaderTemplate>
</MenuItem>
</ContextMenu>
然后像这样改变三个Rectangle的Width和Margin。
更新
正如 unforgiven3 所指出的,Visual Tree 对于 .NET 3.5 看起来有点不同,此更新将解决这个问题。
private void WidestImage_Loaded(object sender, RoutedEventArgs e)
{
Image image = sender as Image;
StackPanel parentStackPanel = VisualTreeHelpers.GetVisualParent<StackPanel>(image);
Grid grid = VisualTreeHelpers.GetVisualParent<Grid>(parentStackPanel);
List<Rectangle> rectangles = VisualTreeHelpers.Get1stLevelVisualChildCollection<Rectangle>(grid);
// .NET 3.5 fix
if (rectangles.Count == 0)
{
ScrollViewer scrollViewer = VisualTreeHelpers.GetVisualParent<ScrollViewer>(grid);
grid = VisualTreeHelpers.GetVisualParent<Grid>(scrollViewer);
rectangles = VisualTreeHelpers.Get1stLevelVisualChildCollection<Rectangle>(grid);
}
double width = Math.Max(28, image.Width + 4);
// 28
rectangles[0].Width = width;
// 28+1 = 29
rectangles[1].Margin = new Thickness(width+1, 2, 0, 2);
// 28+2 = 30
rectangles[2].Margin = new Thickness(width+2, 2, 0, 2);
}
以及 VisualTree Helper 方法的一些实现
public static T GetVisualParent<T>(object childObject) where T : Visual
{
DependencyObject child = childObject as DependencyObject;
// iteratively traverse the visual tree
while ((child != null) && !(child is T))
{
child = VisualTreeHelper.GetParent(child);
}
return child as T;
}
public static List<T> Get1stLevelVisualChildCollection<T>(object parent) where T : Visual
{
List<T> visualCollection = new List<T>();
Get1stLevelVisualChildCollection(parent as DependencyObject, visualCollection);
return visualCollection;
}
private static void Get1stLevelVisualChildCollection<T>(DependencyObject parent, List<T> visualCollection) where T : Visual
{
int count = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < count; i++)
{
DependencyObject child = VisualTreeHelper.GetChild(parent, i);
if (child is T)
{
visualCollection.Add(child as T);
}
}
}
关于wpf - 如何更改 WPF 菜单的图标列大小?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4059626/