0

我有一个Window包含RibbonMenue. 这Window里面有一些UserControls。其中之一UserControlDataGrid. 我创建了一个ICommand允许我从DataGrid.

问题是我不知何故需要ICommands从.RibbonMenuViewModelUserControl

如何创建ICommands可以全局调用的?请注意,由于我需要从中删除行,所以需要ICommand对 my 的引用ViewModelUserControl以此类推。

图像让它更清晰一点,我希望

4

2 回答 2

0

执行“全局命令”的传统 MVVM 方式是使用 CompositeCommand。您将拥有一个 GlobalCommands.cs 文件,其中包含一个名为 GlobalCommands 的静态类。

在其中,您将拥有返回 CompositeCommand 实例的 ICommand 属性。然后,任何对命令感兴趣的 VM 都可以在其构造函数中附加到它:GlobalCommands.SomeCommand.RegisterCommand(...)。您的 UI 将附加到 GlobalCommands 命令。

所以 GlobalCommands 将持有 CompositeCommand ,它只是一个空的 shell / holder 命令,VM 将使用复合命令注册一个普通的 RelayCommand 并处理该命令。多个虚拟机可以使用相同的命令注册,所有虚拟机都会被调用。

更高级的 CompositeCommand 实现还包括 IActiveAware 功能,该功能可以使 CompositeCommand 仅将 canexecute/execute 发送到“活动”虚拟机。

我相信 CompositeCommand 最初来自 Prism,但很多人(包括我自己)刚刚将它分解为用于非 Prism 应用程序。

于 2016-01-27T20:47:52.443 回答
0

我设法得到了你需要的东西,我在这里做了一个单例命令是整个例子(对不起,很长的帖子只是想确保你能正确地工作):

using System;
using System.Windows.Input;

namespace WpfApplication
{
    public class GlobalCommand<T> : ICommand
    {
        #region Fields
        private readonly Action<T> _execute = null;
        private readonly Predicate<T> _canExecute = null;
        private static GlobalCommand<T> _globalCommand; 
        private static readonly object locker = new object();
        #endregion

        #region Constructors

        public static GlobalCommand<T> GetInstance(Action<T> execute)
        {
            return GetInstance(execute, null);
        }
        public static GlobalCommand<T> GetInstance(Action<T> execute, Predicate<T> canExecute)
        {
            lock (locker)
            {
                if (_globalCommand == null)
                {
                    _globalCommand = new GlobalCommand<T>(execute, canExecute);
                }
            }
            return _globalCommand;
        }

        private GlobalCommand(Action<T> execute, Predicate<T> canExecute)
        {
            if (execute == null)
                throw new ArgumentNullException("execute");

            _execute = execute;
            _canExecute = canExecute;
        }

        #endregion

        #region ICommand Members

        public bool CanExecute(object parameter)
        {
            return _canExecute == null || _canExecute((T)parameter);
        }

        public event EventHandler CanExecuteChanged
        {
            add
            {
                if (_canExecute != null)
                    CommandManager.RequerySuggested += value;
            }
            remove
            {
                if (_canExecute != null)
                    CommandManager.RequerySuggested -= value;
            }
        }

        public void Execute(object parameter)
        {
            _execute((T)parameter);
        }

        #endregion
    }
}


视图模型

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows.Input;

namespace WpfApplication
{
    public class ViewModel : INotifyPropertyChanged
    {

        public event PropertyChangedEventHandler PropertyChanged;
        public ObservableCollection<Category> Categories { get; set; }
        public ICommand AddRowCommand { get; set; }
        public ViewModel()
        {
            Categories = new ObservableCollection<Category>()
           {
             new Category(){ Id = 1, Name = "Cat1", Description = "This is Cat1 Desc"},
             new Category(){ Id = 1, Name = "Cat2", Description = "This is Cat2 Desc"},
             new Category(){ Id = 1, Name = "Cat3", Description = "This is Cat3 Desc"},
             new Category(){ Id = 1, Name = "Cat4", Description = "This is Cat4 Desc"}
           };

            this.AddRowCommand = GlobalCommand<object>.GetInstance(ExecuteAddRowCommand, CanExecuteAddRowCommand);
        }

        private bool CanExecuteAddRowCommand(object parameter)
        {
            if (Categories.Count <= 15)
                return true;
            return false;
        }

        private void ExecuteAddRowCommand(object parameter)
        {
            Categories.Add(new Category()
            {
                Id = 1,
                Name = "Cat"+(Categories.Count+1),
                Description = "This is Cat" + (Categories.Count + 1) + " Desc"
            });
        }

    }
}


模型

namespace WpfApplication
{
    public class Category
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
    }
}


主窗口.Xaml

<Window x:Class="WpfApplication.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication"
        Title="MainWindow" Height="500" Width="525">
    <Window.Resources>
        <local:ViewModel x:Key="ViewModel" />
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Ribbon x:Name="RibbonWin"  SelectedIndex="0" Grid.Row="0">
            <Ribbon.QuickAccessToolBar>
                <RibbonQuickAccessToolBar>
                    <RibbonButton x:Name ="Delete" Content="Delete a row" Click="Delete_Click"/>
                </RibbonQuickAccessToolBar>
                </Ribbon.QuickAccessToolBar>
        </Ribbon>
        <UserControl Grid.Row="1" x:Name="UserControl" DataContext="{StaticResource ViewModel}">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="*"/>
                    <RowDefinition Height="Auto"/>
                </Grid.RowDefinitions>
                <DataGrid ItemsSource="{Binding Path=Categories}" AutoGenerateColumns="False" CanUserAddRows="False" Margin="0,10,0,100" Name="DataGrid1" Grid.Row="0" >
                    <DataGrid.Columns>
                        <DataGridTextColumn Header="Id" IsReadOnly="True" Binding="{Binding Id}"/>
                        <DataGridTextColumn Header="Name" IsReadOnly="True" Binding="{Binding Name}"/>
                        <DataGridTextColumn Header="Description" IsReadOnly="True" Binding="{Binding Description}"/>
                    </DataGrid.Columns>
                </DataGrid>
                <Button Content="Add new row" Command="{Binding Path=AddRowCommand}" HorizontalAlignment="Center" Width="75" Grid.Row="1"/>
            </Grid>

        </UserControl>
    </Grid>
</Window>


背后的代码

using System.Windows;

namespace WpfApplication
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Delete_Click(object sender, RoutedEventArgs e)
        {
            GlobalCommand<object>.GetInstance(null).Execute(null);// I'm not quite happy with this but it works
        }
    }
}
于 2016-01-27T21:59:41.327 回答