WPF MenuItem : Mix databound items and static content
Asked Answered
J

1

8

I'd like to build an MRU menu that has the following structure:

File
+=>Recent Files
   +=> Doc1.txt
   +=> Doc2.txt
   -separator-
   +=> Clear entries

This being MVVM, my mru list is databound to the View Model. Because I want to add the separator, and I don't fancy inserting the separator and the clear entry action in the list of items, I'm currently using an itemscontrol container for my menu, but I've got horrible padding issues. Do you have any solution that would allow me to just add MenuItem instances ?

Here's the XAML :

<!-- MRU list -->
<MenuItem Header="_Recent Files" >

    <ItemsControl ItemsSource="{Binding MostRecentlyUsed.Entries,Mode=OneWay}">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <MenuItem Header="{Binding ShortName}" ToolTip="{Binding FileName}" Command="{Binding OpenCommand}"/>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
    <Separator />
    <MenuItem Header="_Clean Entries" Command="{Binding MostRecentlyUsed.CleanCommand}" />
</MenuItem>
<Separator />

Cheers, Florian

Jumbala answered 28/6, 2010 at 14:5 Comment(0)
W
9

Replace the DataTemplate with an ItemContainerStyle as follows:

<MenuItem Header="_Recent Files" ItemsSource="{Binding Commands,Mode=OneWay}">
  <MenuItem.ItemContainerStyle>
    <Style TargetType="{x:Type MenuItem}">
       <Setter Property="Header" Value="{Binding Path=ShortName}" />
       <Setter Property="ToolTip" Value="{Binding Path=FileName}" />
       <Setter Property="Command" Value="{Binding Path=OpenCommand}" />
       <Setter Property="CommandParameter" Value="{Binding Path=OpenParameter}" />
       <Style.Triggers>
         <DataTrigger Binding="{Binding Path=IsSeparator}" Value="true">
           <Setter Property="MenuItem.Template">
             <Setter.Value>
               <ControlTemplate TargetType="{x:Type MenuItem}">
                 <Separator Style="{DynamicResource {x:Static MenuItem.SeparatorStyleKey}}"/>
               </ControlTemplate>
             </Setter.Value>
           </Setter>
         </DataTrigger>
       </Style.Triggers>
     </Style>
   </MenuItem.ItemContainerStyle>
 </MenuItem>

Here is the code I am binding to that is similar to your code (but different):

public class MainViewModel : ViewModelBase
{
  public MainViewModel()
  {
     GoCommand = new DelegateCommand<object>(OnGoCommand, CanGoCommand);
     LoadCommands();
  }

  private List<MyCommand> _commands = new List<MyCommand>();
  public List<MyCommand> Commands
  {
     get { return _commands; }
  }

  private void LoadCommands()
  {
     MyCommand c1 = new MyCommand { OpenCommand = GoCommand, OpenParameter = "1", ShortName = "Doc1", FileName = "Doc1.txt", IsSeparator = false };
     MyCommand c2 = new MyCommand { OpenCommand = GoCommand, OpenParameter = "2", ShortName = "Doc2", FileName = "Doc1.txt", IsSeparator = false };
     MyCommand c3 = new MyCommand { OpenCommand = GoCommand, OpenParameter = "4", ShortName = "", FileName = "", IsSeparator = true };
     MyCommand c4 = new MyCommand { OpenCommand = GoCommand, OpenParameter = "5", ShortName = "_Clean Entries", FileName = "Clean Entries", IsSeparator = false };
     _commands.Add(c1);
     _commands.Add(c2);
     _commands.Add(c3);
     _commands.Add(c4);
  }

  public ICommand GoCommand { get; private set; }
  private void OnGoCommand(object obj)
  {
  }

  private bool CanGoCommand(object obj)
  {
     return true;
  }
}


public class MyCommand
{
  public ICommand OpenCommand { get; set; }
  public string ShortName { get; set; }
  public string FileName { get; set; }
  public string OpenParameter { get; set; }
  public bool IsSeparator { get; set; }
}
Workhouse answered 29/6, 2010 at 3:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.