我尝试将MVVM用于我的应用程序,因为它使事情变得更容易。所以我的菜单项是绑定到具有自定义样式的按钮的数据类(该样式实际上绑定了基础数据)。
事情是这些菜单项可以选择性地添加其他内容,如果不需要,可以设置为Collapsed
。到目前为止,这种方法非常好,但是切换到MVVM会带来一些问题。我需要在某处定义附加内容,并以编程方式将其附加到菜单项。
代码中的设计工作是一种糟糕的方法。所以我想到了使用WPF资源系统。我尝试将内容插入到有效的资源中。我可以按原样指定控件。
但是当我尝试通过FindResource()
- 方法加载它时,它找不到任何东西。我把它放到不同的地方,并在不同的状态调用代码(Window构造函数,Loaded-event,...)但是它无处可以找到这个控件。
我尝试使用Application.Current.Resources[...]
,Application.Current.FindResource(...)
以及与Window类相同的操作。它总是出现ResourceReferenceKeyNotFoundException
。
此外,当放入资源文件时,它给我一个解析异常,表示我不能在资源对象上使用x:Name
。所以我基本上不能使用整个系统,因为我需要名称才能在该控件的子元素之间绑定东西。
这甚至可能吗?它是否打算以这种方式使用?有没有更好的方法来实现这一目标?再一次,我没有得到WPF的设计原则......
PS:我尝试使用 Page 和 Resource 作为.xaml文件的编译选项。
那是控件:
<views:AnimatedStackPanel x:Key="LiftMenuAnalyzeContent" HorizontalAlignment="Stretch" Orientation="Vertical" >
<views:AnimatedStackPanel.Children>
<StackPanel x:Name="PaneAnalysisStep" Orientation="Horizontal" HorizontalAlignment="Center">
<shared:Triangle Width="20" Height="24" ApexSide="Left"
Fill="#ff8000" />
<Border HorizontalAlignment="Stretch" VerticalAlignment="Center" Background="#ff8000"
BorderBrush="#ff8000" BorderThickness="0" Padding="4">
<TextBlock x:Name="TxtAnalysisStep" Text="Analyzing" />
</Border>
<shared:Triangle Width="20" Height="24" ApexSide="Right"
Fill="#ff8000" />
</StackPanel>
<Grid x:Name="GridAnalysisInfo" HorizontalAlignment="Center" VerticalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="30" />
<ColumnDefinition Width="10" />
<ColumnDefinition Width="50" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="27" />
<RowDefinition Height="27" />
<RowDefinition Height="27" />
</Grid.RowDefinitions>
<Label x:Name="LblObjectsFound" Grid.Row="1" Grid.Column="0"
Content="0" />
<Label Grid.Row="1" Grid.Column="2" HorizontalAlignment="Left"
Content="Targets" />
<Label x:Name="LblIssuesFound" Grid.Row="2" Grid.Column="0"
Content="0" />
<Label Grid.Row="2" Grid.Column="2" HorizontalAlignment="Left"
Content="Issues" />
<Label x:Name="LblErrorsFound" Grid.Row="3" Grid.Column="0"
Content="0" />
<Label Grid.Row="3" Grid.Column="2" HorizontalAlignment="Left"
Content="Errors" />
</Grid>
<TextBlock Margin="0,5,0,0" FontWeight="Bold"
Text="Not possible." TextAlignment="Center" TextWrapping="Wrap" />
</views:AnimatedStackPanel.Children>
答案 0 :(得分:0)
如果要在MVVM中创建动态菜单,则需要首先为包含标题的每个菜单项声明一个视图模型,为动态内容指定一个字段(稍后详细介绍)和任何列表子菜单项:
public class MenuItemViewModel : ViewModelBase
{
public string Header {get; set;}
public object Content {get; set;}
public MenuItemViewModel[] Children { get; set; }
}
然后您的视图模型需要创建这些结构的树:
public class DemoViewModel : ViewModelBase
{
public MenuItemViewModel[] MenuItems {get; set;}
public DemoViewModel()
{
this.MenuItems = new MenuItemViewModel[]
{
new MenuItemViewModel{
Header = "File", Content="icon.png",
Children = new MenuItemViewModel[]
{
new MenuItemViewModel{Header="Open", Content="icon.png"},
new MenuItemViewModel{Header="Save", Content="icon.png"},
new MenuItemViewModel{Header="Close", Content="icon.png"},
}
},
new MenuItemViewModel{
Header = "Edit", Content="icon.png",
Children = new MenuItemViewModel[]
{
new MenuItemViewModel{Header="Cut", Content="icon.png"},
new MenuItemViewModel{Header="Copy", Content="icon.png"},
new MenuItemViewModel{Header="Paste", Content="icon.png"},
}
}
};
}
}
显示此菜单只需将Menu绑定到MenuItems并指定HeirarchicalDataTemplate,以便它知道如何绘制它们:
<Menu ItemsSource="{Binding MenuItems}" DockPanel.Dock="Top">
<Menu.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:MenuItemViewModel}" ItemsSource="{Binding Children}">
<ContentPresenter Content="{Binding Header}" />
</HierarchicalDataTemplate>
</Menu.Resources>
</Menu>
结果:
在此示例中,我明确地让ContentPresenter显示Header
属性中的内容,但您可以将其覆盖到您想要的任何内容。在我的原始视图模型中,我添加了Content
属性并将它们全部设置为icon.png
,我假设它是一种资源,我可以使用带有BitmapImage的图像来显示它源:
<HierarchicalDataTemplate DataType="{x:Type local:MenuItemViewModel}" ItemsSource="{Binding Children}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Header}" />
<Image Width="16" Height="16">
<Image.Source>
<BitmapImage UriSource="{Binding Content}" />
</Image.Source>
</Image>
</StackPanel>
</HierarchicalDataTemplate>
结果:
在这个特定示例中,我将其硬编码为图像并假设Content
将始终是一个字符串,但使用DataTemplating,您可以使Content
任何您想要的类并指定每个应如何显示。