How to resize column of WPF menu icon?

I have a WPF ContextMenu that looks like this:

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

The problem is that the icon overlaps the icon column, for example: Icon is too big for menu

How to increase the width of a column of a menu icon so that the large icon is centered inside the column?

+3
source share
1 answer

This is just a workaround, but it will work for each width for the MenuItem column.
Results will vary from this.

alt text

For this

alt text

Everything in the menu is built dynamically, except for the "Column" menu icon.
Using Snoop, we see that it actually consists of three rectangles

alt text

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>  

, .

UPDATE
- .NET 3.5, unporgiven3, .

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

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);
        }
    }
}
+4

Source: https://habr.com/ru/post/1772269/


All Articles