2010-10-30 28 views
3

我有一個WPF文本菜單,看起來像這樣:如何更改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> 

的問題是,該圖標重疊的圖標欄,就像這樣: Icon is too big for menu

如何增加菜單的圖標列的寬度這樣大圖標在列中居中?

+0

一些實施好像你需要改變你的菜單項的模板。我建議使用Blend編輯模板或查看Kaxaml的SimpleStyles。 – robertos 2010-10-31 10:15:07

回答

4

這只是一個解決方法,但它將適用於MenuItem列的每個寬度。
結果將從此

alt text

改變要在菜單此

alt text

一切都是動態構建除了菜單的圖標「列」
使用snoop我們可以看到它實際上由三個矩形組成

alt text

第一矩形得到的28
一個寬度的第二個矩形得到1:1的寬度和的餘量(29,2,0,2)
第三矩形得到1: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
可視樹是由unforgiven3指出,看起來有點不同了.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); 
     } 
    } 
} 
+1

不幸的是,這似乎不適用於.NET 3.5。 – 2010-11-02 01:27:39

+1

我會研究它 – 2010-11-02 07:44:17

+1

Visual Tree在.NET 3.5中看起來有點不同。更新了我的答案。 – 2010-11-02 08:07:42

相關問題