从集合创建菜单项
Create MenuItems from Collection
我尝试创建集合项的 MenuItems - 但失败了。详细说明:我有一个简单的 class ClassA,它定义了一个字符串-属性 'HeadText'。
在我的 MainViewModel 中,我定义了一个 ObservableCollection 属性。该集合包含 3 个项目。现在在 XAML 中,我想创建这 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>
但我得到的只是一个空的菜单栏。我有什么想法可以做到这一点吗?
视图模型和 class 类 A:
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; }
}
提前致谢。
编辑:
如果我写这个,它会起作用:
<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>
但我想换一种方式。我很感兴趣为什么另一种方法不起作用。
我找到了答案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 和 A 类:
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。这是为动态菜单项和静态菜单项完成的。因为MenuItemclass中没有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>
也许有更好的解决方案。如果是这样,请告诉我。
我尝试创建集合项的 MenuItems - 但失败了。详细说明:我有一个简单的 class ClassA,它定义了一个字符串-属性 'HeadText'。 在我的 MainViewModel 中,我定义了一个 ObservableCollection 属性。该集合包含 3 个项目。现在在 XAML 中,我想创建这 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>
但我得到的只是一个空的菜单栏。我有什么想法可以做到这一点吗?
视图模型和 class 类 A:
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; }
}
提前致谢。
编辑:
如果我写这个,它会起作用:
<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>
但我想换一种方式。我很感兴趣为什么另一种方法不起作用。
我找到了答案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 和 A 类:
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。这是为动态菜单项和静态菜单项完成的。因为MenuItemclass中没有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>
也许有更好的解决方案。如果是这样,请告诉我。