我尝试在我的应用程序中创建最近的文件子菜单。我的代码基于 https://www.itcodar.com/csharp/wpf-how-to-create-menu-and-submenus-using-binding.html
的示例当我尝试以这样的方式使用静态菜单项时:
<MenuItem Header="_File">
<MenuItem Header="_Open..." Command="Open"/>
<MenuItem Header="_Save..." Command="Save"/>
<Separator></Separator>
<MenuItem Header="_Close" Command="Close"/>
<Separator></Separator>
<MenuItem Header="_Recent Files">
<Menu DockPanel.Dock="Top" ItemsSource="{Binding MenuItems}">
<Menu.ItemContainerStyle>
<Style TargetType="{x:Type MenuItem}">
<Setter Property="Command" Value="{Binding Command}" />
</Style>
</Menu.ItemContainerStyle>
<Menu.ItemTemplate>
<HierarchicalDataTemplate DataType="{x:Type local:MenuItemViewModel}" ItemsSource="{Binding Path=MenuItems}">
<TextBlock Text="{Binding Header }"/>
</HierarchicalDataTemplate>
</Menu.ItemTemplate>
</Menu>
</MenuItem>
</MenuItem>
通过单击此项目,我在打开的菜单左侧看到水平菜单,而不是垂直菜单。
我将此项目放置在动态菜单中:
<MenuItem Header="_File">
<MenuItem Header="_Open..." Command="Open"/>
<MenuItem Header="_Save..." Command="Save"/>
<Separator></Separator>
<MenuItem Header="_Close" Command="Close"/>
<Separator></Separator>
<Menu DockPanel.Dock="Top" ItemsSource="{Binding MenuItems}">
<Menu.ItemContainerStyle>
<Style TargetType="{x:Type MenuItem}">
<Setter Property="Command" Value="{Binding Command}" />
</Style>
</Menu.ItemContainerStyle>
<Menu.ItemTemplate>
<HierarchicalDataTemplate DataType="{x:Type local:MenuItemViewModel}" ItemsSource="{Binding Path=MenuItems}">
<TextBlock Text="{Binding Header }"/>
</HierarchicalDataTemplate>
</Menu.ItemTemplate>
</Menu>
</MenuItem>
我在打开的菜单下方有垂直子菜单。这不完全是我想要的,但可以接受。 但主要问题发生在我启动应用程序时 - 最近的文件列表未随新打开的文件更新。从申请开始起就保持不变。
所以我很有趣,如何在运行时更新动态菜单,并且作为障碍,如何将最近的文件列表放置在调用菜单的左侧?
示例:
using Microsoft.Win32;
using Simplified;
using System.Collections.ObjectModel;
using System.IO;
using System.Windows;
namespace Core2023.SO.Old_Nick.question77731533
{
public class FilesViewModel : ViewModelBase
{
public ObservableCollection<FileInfo> Files { get; } = new();
public RelayCommand OpenFile => GetCommand(OpenFileExecute);
public RelayCommand ReOpenFile => GetCommand<FileInfo>(OpenFileExecute);
private void OpenFileExecute()
{
OpenFileDialog dialog = new OpenFileDialog();
if (dialog.ShowDialog() == true)
OpenFileExecute(new FileInfo(dialog.FileName));
}
private void OpenFileExecute(FileInfo fileInfo)
{
int index = Files.IndexOf(fileInfo);
if (index < 0)
{
Files.Insert(0, fileInfo);
while (Files.Count > 10)
{
Files.RemoveAt(Files.Count - 1);
}
}
else
{
Files.Move(index, 0);
}
MessageBox.Show($"Open File: {fileInfo.FullName}");
}
}
}
<Window x:Class="Core2023.SO.Old_Nick.question77731533.FilesWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Core2023.SO.Old_Nick.question77731533" xmlns:io="clr-namespace:System.IO;assembly=System.IO.FileSystem"
mc:Ignorable="d"
Title="FilesWindow" Height="450" Width="800"
DataContext="{DynamicResource vm}">
<Window.Resources>
<local:FilesViewModel x:Key="vm"/>
</Window.Resources>
<Grid>
<Menu>
<MenuItem Header="File">
<MenuItem Header="Open" Command="{Binding OpenFile}"/>
<MenuItem Header="Recent Files" ItemsSource="{Binding Files}">
<MenuItem.ItemTemplate>
<DataTemplate DataType="{x:Type io:FileInfo}">
<Button Content="{Binding FullName}"
Command="{Binding ReOpenFile, Mode=OneWay, Source={StaticResource vm}}"
CommandParameter="{Binding}"/>
</DataTemplate>
</MenuItem.ItemTemplate>
</MenuItem>
</MenuItem>
</Menu>
</Grid>
</Window>