当前位置:网站首页 / WPF / 正文

2020 WPF 取经之路第11天 - menuitem动态生成

时间:2020年04月26日 | 作者 : aaronyang | 分类 : WPF | 浏览: 303次 | 评论 0

对于网上对ICommand的封装对应的Model,有很多

这里找到一个简单的SimpleCommand

public class SimpleCommand : ICommand
    {
        public SimpleCommand(Func<object, bool> canExecute = null, Action<object> execute = null)
        {
            this.CanExecuteDelegate = canExecute;
            this.ExecuteDelegate = execute;
        }

        public Func<object, bool> CanExecuteDelegate { get; set; }

        public Action<object> ExecuteDelegate { get; set; }

        public bool CanExecute(object parameter)
        {
            var canExecute = this.CanExecuteDelegate;
            return canExecute == null || canExecute(parameter);
        }

        public event EventHandler CanExecuteChanged
        {
            add => CommandManager.RequerySuggested += value;
            remove => CommandManager.RequerySuggested -= value;
        }

        public void Execute(object parameter)
        {
            this.ExecuteDelegate?.Invoke(parameter);
        }
    }

定义个MenuItem对应的Model类

 public class MenuItemModelBase
    {
        public string Name { get; set; }

        public MenuItemModelBase()
        {
            this.MenuCommandCommand = new SimpleCommand(o => true, this.DoMenuCommandCommand);
        }

        public ICommand MenuCommandCommand { get; }

        protected virtual void DoMenuCommandCommand(object sender)
        {
            MessageBox.Show("父亲:" + "Do");
        }
    }

增加一个文件菜单组和 主页面vm    

 public class FilesMenuItemModel: MenuItemModelBase
    {
        protected override void DoMenuCommandCommand(object sender)
        {
            MessageBox.Show("执行:"+ Name);
        }
    }
    public class MainWindowVM
    {
        public List<MenuItemModelBase> FileMenuItems { get; set; }
    }

MainWindow后台

    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : MetroWindow
    {
        MainWindowVM vm = new MainWindowVM();
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = vm;
            FilesMenuItemModel fmi1 = new FilesMenuItemModel() { Name="新建"};
            FilesMenuItemModel fmi2 = new FilesMenuItemModel() { Name = "打开" };
            FilesMenuItemModel fmi3 = new FilesMenuItemModel() { Name = "保存" };
            FilesMenuItemModel fmi4 = new FilesMenuItemModel() { Name = "保存全部" };
            vm.FileMenuItems = new List<FilesMenuItemModel>();
            vm.FileMenuItems.Add(fmi1);
            vm.FileMenuItems.Add(fmi2);
            vm.FileMenuItems.Add(fmi3);
            vm.FileMenuItems.Add(fmi4);

        }
        <Menu Grid.Row="0" Margin="5" HorizontalAlignment="Left" VerticalAlignment="Stretch">
            <MenuItem Header="文件(_F)" ItemsSource="{Binding FileMenuItems, Mode=OneWay}" />
        </Menu>

image.png

我们看MenuItem继承MenuBase

image.png

所以既然是ItemsControl,那就好办了。

     <Menu Grid.Row="0" Margin="5" HorizontalAlignment="Left" VerticalAlignment="Stretch">
            <MenuItem Header="文件(_F)" ItemsSource="{Binding FileMenuItems, Mode=OneWay}">
                <MenuItem.ItemContainerStyle>
                    <Style BasedOn="{StaticResource MahApps.Styles.MenuItem}" TargetType="{x:Type MenuItem}">
                        <Setter Property="Command" Value="{Binding MenuCommandCommand}" />
                        <Setter Property="Header" Value="{Binding Name, Mode=OneWay}" />
                    </Style>

                </MenuItem.ItemContainerStyle>
            </MenuItem>
        </Menu>

image.png

image.png


右键菜单

   <Grid Width="200" Height="200" Background="Gray" Grid.Row="1">
            <Grid.ContextMenu>
                <ContextMenu ItemsSource="{Binding FileMenuItems, Mode=OneWay}">
                    <ContextMenu.ItemContainerStyle>
                        <Style BasedOn="{StaticResource MahApps.Styles.MenuItem}" TargetType="{x:Type MenuItem}">
                            <Setter Property="Command" Value="{Binding MenuCommandCommand}" />
                            <Setter Property="Header" Value="{Binding Name, Mode=OneWay}" />
                        </Style>

                    </ContextMenu.ItemContainerStyle>
                </ContextMenu>
            </Grid.ContextMenu>
        </Grid>

image.png


如果菜单多级菜单怎么弄:

修改父Model,增加Children

   public class MenuItemModelBase
    {
        public string Name { get; set; }

        public MenuItemModelBase()
        {
            this.MenuCommandCommand = new SimpleCommand(o => true, this.DoMenuCommandCommand);
        }

        public ICommand MenuCommandCommand { get; }

        protected virtual void DoMenuCommandCommand(object sender)
        {
            MessageBox.Show("父亲:" + "Do");
        }
        private ObservableCollection<MenuItemModelBase> _children=new ObservableCollection<MenuItemModelBase>();
        public ObservableCollection<MenuItemModelBase> Children
        {
            get { return _children; }
            set
            {
                _children = value; 
            }
        }

    }
  public partial class MainWindow : MetroWindow
    {
        MainWindowVM vm = new MainWindowVM();
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = vm;
            FilesMenuItemModel fmi = new FilesMenuItemModel() { Name = "文件(_F)" };
 
            FilesMenuItemModel fmi1 = new FilesMenuItemModel() { Name="新建"};
            FilesMenuItemModel fmi2 = new FilesMenuItemModel() { Name = "打开" };
            FilesMenuItemModel fmi3 = new FilesMenuItemModel() { Name = "保存" };
            FilesMenuItemModel fmi4 = new FilesMenuItemModel() { Name = "保存全部" };
            vm.FileMenuItems = new List<FilesMenuItemModel>();
            fmi.Children.Add(fmi1);
            fmi.Children.Add(fmi2);
            fmi.Children.Add(fmi3);
            fmi.Children.Add(fmi4);

            
            FilesMenuItemModel fmi1_1 = new FilesMenuItemModel() { Name = "桌面" };
            FilesMenuItemModel fmi1_2 = new FilesMenuItemModel() { Name = "网页" };
            FilesMenuItemModel fmi1_3 = new FilesMenuItemModel() { Name = "游戏" };
            FilesMenuItemModel fmi1_4 = new FilesMenuItemModel() { Name = "APP" };
            FilesMenuItemModel fmi1_4_1 = new FilesMenuItemModel() { Name = "IOS" };
            FilesMenuItemModel fmi1_4_2 = new FilesMenuItemModel() { Name = "安卓" };
            fmi1_4.Children.Add(fmi1_4_1);
            fmi1_4.Children.Add(fmi1_4_2);
            fmi1.Children.Add(fmi1_1);
            fmi1.Children.Add(fmi1_2);
            fmi1.Children.Add(fmi1_3);
            fmi1.Children.Add(fmi1_4);

            vm.FileMenuItems.Add(fmi);
        }


        //private void Button_Click(object sender, RoutedEventArgs e)
        //{
        //    this.IgnoreTaskbarOnMaximize = this.IgnoreTaskbarOnMaximize?false:true;
        //}
    }

前台测试绑定

<mah:MetroWindow x:Class="AyTestWindowDemo.MainWindow"
        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" BorderThickness="1"
        xmlns:local="clr-namespace:AyTestWindowDemo" xmlns:mah="urn:mah" xmlns:zex="urn:controlzex"  mc:Ignorable="d" WindowStartupLocation="CenterScreen" GlowBrush="blue"
        Title="AY测试主题" Height="800" Width="1000" >
    
    <Grid Margin="0,0,0,0" Background="Transparent">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <Menu Grid.Row="0" Margin="5" HorizontalAlignment="Left" VerticalAlignment="Stretch" ItemsSource="{Binding FileMenuItems}">
            <Menu.ItemContainerStyle>
                <Style BasedOn="{StaticResource MahApps.Styles.MenuItem}" TargetType="{x:Type MenuItem}">
                    <Setter Property="Command" Value="{Binding MenuCommandCommand}" />
                    <Setter Property="Header" Value="{Binding Name, Mode=OneWay}" />
                    <Setter Property="ItemsSource" Value="{Binding Children}" />
                </Style>
            </Menu.ItemContainerStyle>
        </Menu>
        <Grid Width="200" Height="200" Background="Gray" Grid.Row="1">
            <Grid.ContextMenu>
                <ContextMenu ItemsSource="{Binding FileMenuItems, Mode=OneWay}">
                    <ContextMenu.ItemContainerStyle>
                        <Style BasedOn="{StaticResource MahApps.Styles.MenuItem}" TargetType="{x:Type MenuItem}">
                            <Setter Property="Command" Value="{Binding MenuCommandCommand}" />
                            <Setter Property="Header" Value="{Binding Name, Mode=OneWay}" />
                            <Setter Property="ItemsSource" Value="{Binding Children}" />
                        </Style>
                    </ContextMenu.ItemContainerStyle>
                </ContextMenu>
            </Grid.ContextMenu>
        </Grid>
        <!--<Button Content="测试是" Width="100" Height="20" />
        <zex:Glow Direction="Bottom" GlowBrush="Red" IsGlow="True" NonActiveGlowBrush="Blue" Height="3"/>-->
    </Grid>
</mah:MetroWindow>

image.png

image.png










拓展:

image.png

当然配合HierarchicalDataTemplate

文章:打开


还有个搜到的,文章打开

暂时不知道,下面代码的用处

 <c:CommandReference x:Key="AddModeCommandRef" Command="{Binding Path=AddModeCommand}"/>

public ICommand AddModeCommand { get; set; }


   <MenuItem Header="添加" Command="{StaticResource AddModeCommandRef}" >                

                <MenuItem.Icon>

                    <Image Source="../Images/Add.png" Width="16" Height="16" />

                </MenuItem.Icon>

            </MenuItem>


增加一个CommandReference

public class CommandReference : Freezable, ICommand, ICommandSource
    {
        public CommandReference()
        {

        }

        public static readonly DependencyProperty CommandParameterProperty =
          DependencyProperty.Register(
              "CommandParameter",
              typeof(object),
              typeof(CommandReference),
              new PropertyMetadata((object)null));

        public object CommandParameter
        {
            get
            {
                return (object)GetValue(CommandParameterProperty);
            }
            set
            {
                SetValue(CommandParameterProperty, value);
            }
        }

        public static readonly DependencyProperty CommandTargetProperty =
           DependencyProperty.Register(
               "CommandTarget",
               typeof(IInputElement),
               typeof(CommandReference),
               new PropertyMetadata((IInputElement)null));

        public IInputElement CommandTarget
        {
            get
            {
                return (IInputElement)GetValue(CommandTargetProperty);
            }
            set
            {
                SetValue(CommandTargetProperty, value);
            }
        }

        public static readonly DependencyProperty CommandProperty = DependencyProperty.Register("Command", typeof(ICommand), typeof(CommandReference), new PropertyMetadata(new PropertyChangedCallback(OnCommandChanged)));

        public ICommand Command
        {
            get { return (ICommand)GetValue(CommandProperty); }
            set { SetValue(CommandProperty, value); }
        }

        #region ICommand Members

        public bool CanExecute(object parameter)
        {
            if (Command != null)
                return Command.CanExecute(CommandParameter);
            return false;
        }

        public void Execute(object parameter)
        {
            Command.Execute(CommandParameter);
        }

        public event EventHandler CanExecuteChanged;

        private static void OnCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            CommandReference commandReference = d as CommandReference;
            ICommand oldCommand = e.OldValue as ICommand;
            ICommand newCommand = e.NewValue as ICommand;

            if (oldCommand != null)
            {
                oldCommand.CanExecuteChanged -= commandReference.CanExecuteChanged;
            }
            if (newCommand != null)
            {
                newCommand.CanExecuteChanged += commandReference.CanExecuteChanged;
            }
        }

        #endregion

        #region Freezable

        protected override Freezable CreateInstanceCore()
        {
            throw new NotImplementedException();
        }

        #endregion
    }




























推荐您阅读更多有关于“WPF4.5,”的文章

猜你喜欢

额 本文暂时没人评论 来添加一个吧

发表评论

必填

选填

选填

必填

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

  查看权限

合肥科大智能常年招聘.NET,Java,Web前端,有想找想换工作的私聊我AY唯一QQ:875556003和AY交流

抖音号:wpfui,可以看到我的很多作品效果

AYUI8社区版Github地址:前往获取

作者:杨洋(AaronYang简称AY,安徽六安人)目前是个人,还没公司AY唯一QQ:875556003和AY交流

高中学历,2015年1月17日开始,兴趣学习研究WPF,目前工作繁忙,不接任何活

声明:AYUI7个人与商用免费,源码可购买。部分DEMO不免费.AY主要靠卖技术服务挣钱

不是从我处购买的ayui7源码,我不提供任何技术服务,如果你举报从哪里买的,我可以帮你转正为我的客户,并送demo

查看捐赠

AYUI7.X MVC教程 更新如下:

第一课 第二课 程序加密教程

vs2015 企业版密钥HM6NR-QXX7C-DFW2Y-8B82K-WTYJV

vs2017 企业版密钥NJVYC-BMHX2-G77MM-4XJMR-6Q8QF

标签列表