2015-02-10 2 views
0

Я попытался создать MenuItems элементов коллекции - и не удалось. В деталях: у меня есть простой класс ClassA, который определяет строковое свойство «HeadText». В моем MainViewModel я определил свойство ObservableCollection. Коллекция заполнена тремя предметами. Теперь в XAML я хочу создать MenuItems этих 3 элементов типа ClassA. Я сделал следующее:Создать MenuItems из коллекции

<Window.Resources> 
    <CompositeCollection x:Key="CollA"> 
     <ItemsControl ItemsSource="{Binding Path=MItems}"> 
      <ItemsControl.ItemTemplate> 
       <DataTemplate> 
        <MenuItem Header="{Binding HeadText}"/> 
       </DataTemplate> 
      </ItemsControl.ItemTemplate> 
     </ItemsControl> 
    </CompositeCollection> 
</Window.Resources> 

<Grid> 
    <Menu DockPanel.Dock="Top" ItemsSource="{Binding Source={StaticResource CollA}}"/> 
</Grid> 

Но я получаю пустой строке меню. Любые идеи, как я могу это сделать?

модели представления и класс ClassA:

public class MainVM 
{ 
    public MainVM() { 
     _mItems.Add(new ClassA() { HeadText = "A" }); 
     _mItems.Add(new ClassA() { HeadText = "B" }); 
     _mItems.Add(new ClassA() { HeadText = "C" }); 
    } 

    private ObservableCollection<ClassA> _mItems = new ObservableCollection<ClassA>(); 
    public ObservableCollection<ClassA> MItems{ 
     get { return _mItems; } 
    } 
} 

public class ClassA 
{ 
    public ClassA() { } 
    public String HeadText { get; set; } 
} 

Спасибо заранее.

Edit:

Если я пишу это, он работает:

<Menu DockPanel.Dock="Top" ItemsSource="{Binding MItems}"> 
    <Menu.ItemContainerStyle> 
     <Style TargetType="MenuItem" BasedOn="{StaticResource {x:Type MenuItem}}"> 
      <Setter Property="Header" Value="{Binding HeadText}"/> 
     </Style> 
    </Menu.ItemContainerStyle> 
</Menu> 

Но я хочу сделать это по-другому. И меня интересует, почему другой способ не работает.

ответ

0

Я нашел ответ here. Мой первый XAML выглядел следующим образом:

<Window.DataContext> 
     <local:MainVM/> 
    </Window.DataContext> 

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

    <StackPanel> 
     <Menu DockPanel.Dock="Top"> 
      <Menu.ItemContainerStyle> 
       <Style TargetType="MenuItem"> 
        <Setter Property="Header" Value="{Binding HeadText}"/> 
       </Style> 
      </Menu.ItemContainerStyle> 
     <Menu.ItemsSource> 
      <CompositeCollection> 
       <MenuItem Header="Static 1"/> 
       <MenuItem Header="Static 2"/> 
       <CollectionContainer Collection="{Binding Source={StaticResource source}}"/> 
       <MenuItem Header="Static 3"/> 
      </CompositeCollection> 
     </Menu.ItemsSource> 
    </Menu> 
</StackPanel> 

И в MainVM.cs и ClassA:

public class MainVM 
{ 
    public MainVM() { 
     _mItems.Add(new ClassA() { HeadText = "Dyn1" }); 
     _mItems.Add(new ClassA() { HeadText = "Dyn2" }); 
     _mItems.Add(new ClassA() { HeadText = "Dyn3" }); 
    } 

    private ObservableCollection<ClassA> _mItems = new ObservableCollection<ClassA>(); 
    public ObservableCollection<ClassA> MItems{ 
     get { return _mItems; } 
    } 
} 

public class ClassA 
{ 
    public ClassA() { } 

    private string _text = ""; 
    public String HeadText { 
     get { return _text; } 
     set { _text = value; } 
    } 
} 

Это прекрасно работает, но вы должны заметить, что Visual Studio даст вам BindingExpression ошибки в случае, если вы на самом деле смешивать статические и динамические пункты меню.

Причина этого заключается в том, что синтаксический анализатор XAML применяет указанный ItemContainerStyle к динамическому и к элементам статического меню: он создает новый элемент MenuItem и привязывает его свойство HeadText к свойству Header только что созданного MenuItem. Это делается для динамических элементов меню, а также для статических. Поскольку в классе MenuItem отсутствует свойство HeadText, отображается ошибка.

Приложение не будет разбиваться, но это нехорошее решение. Обходным путем для этого является разделение MenuBar следующим образом:

<StackPanel> 
     <Grid DockPanel.Dock="Top"> 
      <Grid.ColumnDefinitions> 
       <ColumnDefinition Width="Auto"/> 
       <ColumnDefinition Width="Auto"/> 
       <ColumnDefinition Width="*"/> 
      </Grid.ColumnDefinitions> 
      <Menu Grid.Column="0"> 
       <MenuItem Header="Static 1"/> 
       <MenuItem Header="Static 2"/> 
      </Menu> 
      <Menu Grid.Column="1"> 
       <Menu.ItemContainerStyle> 
        <Style TargetType="MenuItem"> 
         <Setter Property="Header" Value="{Binding HeadText}"/> 
        </Style> 
       </Menu.ItemContainerStyle> 
       <Menu.ItemsSource> 
        <CompositeCollection> 
         <CollectionContainer Collection="{Binding Source={StaticResource source}}"/> 
        </CompositeCollection> 
       </Menu.ItemsSource> 
      </Menu> 
      <Menu Grid.Column="2"> 
       <MenuItem Header="Static 3"/> 
      </Menu> 
     </Grid> 
    </StackPanel> 

Возможно, есть более приятное решение. Дайте мне знать, если это так.