vice_versa
vice_versa

Reputation: 99

Binding Error on dynamic and static MenuItems in WPF Application

in my WPF Application I create a Menu from a dynamic source (XML). I combined this with a static MenuItem, it runs fine but I get some errors on the static MenuItem. The Menu looks like this

Entity
- dynamic menu items
- separator
- static menu item

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.ItemsControl', AncestorLevel='1''. BindingExpression:Path=HorizontalContentAlignment; DataItem=null; target element is 'MenuItem' (Name=''); target property is 'HorizontalContentAlignment' (type 'HorizontalAlignment')

Same for VerticalAlignment and after I open the Menu, I get this error too

System.Windows.Data Error: 40 : BindingExpression path error: 'MenuItemName' property not found on 'object' ''ModViewModel' (HashCode=13278932)'. BindingExpression:Path=MenuItemName; DataItem='ModViewModel' (HashCode=13278932); target element is 'MenuItem' (Name=''); target property is 'Header' (type 'Object')

The XAML for the binding

<MenuItem Header="_Entity">
    <MenuItem.ItemsSource>
        <CompositeCollection>
            <CollectionContainer Collection="{Binding Source={StaticResource MenuItems}}" />
            <Separator></Separator>
            <MenuItem Header="Edit Templates"/>
        </CompositeCollection>
    </MenuItem.ItemsSource>
    <MenuItem.ItemContainerStyle>
        <Style TargetType="MenuItem">
            <Setter Property="MenuItem.Header" Value="{Binding MenuItemName}"/>
            <Setter Property="CommandParameter" Value="{Binding Components}"/>
        </Style>
     </MenuItem.ItemContainerStyle>
</MenuItem>

Is there a way to separate the static from the dynamic MenuItem so the static MenuItem doesn't use the ItemContainerStyle? Or what causes the errors? If you need more Code, please tell me.

EDIT:

public ObservableCollection<Models.EntityMenuItem> MenuItems
{
    get { return _menuItem; }
    set
    {
        _menuItem = value;
        OnPropertyChanged();
    }
}

public class EntityMenuItem
{
    public string MenuItemName { get; set; }
    public Dictionary<string,bool> Components { get; set; }
}

Upvotes: 1

Views: 964

Answers (1)

Abin
Abin

Reputation: 2956

This works for me,

 <Window.Resources>
    <CollectionViewSource x:Key="FilterOptionsBridge" Source="{Binding Path=MyProperty}" />
 </Window.Resources>

ViewModelProperty:

public List<string> MyProperty { get; private set; }

In Constructor of ViewModel:

MyProperty = new List<string>();
        MyProperty.Add("Menu1");

MenuItem:

  <MenuItem>
     <MenuItem.ItemsSource>
        <CompositeCollection>
           <CollectionContainer Collection="{Binding Source={StaticResource FilterOptionsBridge}}" />
            <Separator></Separator>
            <MenuItem Header="Hello"></MenuItem>
        </CompositeCollection>                            
      </MenuItem.ItemsSource>
    </MenuItem>

For using commands you have to create style like below,

 <Style TargetType="MenuItem" >
     <Setter Property="Header" Value="{Binding Path=Title}"/>         
     <Setter Property="Command" Value="{Binding Path=Command}"/>
     <Setter Property="CommandParameter" Value="{Binding Path=CommandParameter}"/>
 </Style>

now here it looks like,

 <MenuItem>
    <MenuItem.Style>
       <Style TargetType="MenuItem">                            
          <Setter Property="Command" Value="{Binding Path=Command}"/>
          <Setter Property="CommandParameter" Value="{Binding Path=CommandParameter}"/>
       </Style>
    </MenuItem.Style>
  <MenuItem.ItemsSource>
 <CompositeCollection>
     <CollectionContainer Collection="{Binding Path=Title, Source={StaticResource FilterOptionsBridge}}" />
        <Separator></Separator>
            <MenuItem Header="Hello"></MenuItem>
      </CompositeCollection>                            
     </MenuItem.ItemsSource>
    </MenuItem>

Your VM collection like,

 public List<Menuitems> MyProperty { get; private set; }

Menuitems.cs like,

 public class Menuitems //Impliment INotifyPropertyChanged Interface
    {
        private List<string> _Title = new List<string>();
        private ICommand _Command;
        private object _Commandparameter;            
        public List<string> Title
        {
            get { return _Title; }
            set { _Title = value; NotifyPropertyChanged(); }
        }
        public ICommand Command
        {
            get { return _Command; }
            set { _Command = value; NotifyPropertyChanged(); }
        }
        public object CommandParameter
        {
            get { return _Commandparameter; }
            set { _Commandparameter = value; NotifyPropertyChanged(); }
        }           
    }

In my VM constructor,

 var menu1 = new Menuitems() { Title = new List<string>() {"Menu1","Menu2" }, Command=command, CommandParameter=commandparameter };            
        MyProperty = new List<Menuitems>() { menu1 };

This Link gives good example for CollectionContainer

Upvotes: 0

Related Questions