Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/311.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用动态命令的MVVM_C#_.net_Wpf - Fatal编程技术网

C# 使用动态命令的MVVM

C# 使用动态命令的MVVM,c#,.net,wpf,C#,.net,Wpf,我需要创建一个能够创建动态命令的类,我可以绑定到该类。我有一个带有插件的高度动态应用程序,开发人员只在后端创建插件,并从后端控制所有事情。前端是在另一个“远程”应用程序中创建的,该应用程序将后端作为DataContext。下面是一个示例(不是完整的示例),只是为了说明我想做什么: <Window x:Class="WpfApplication7.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/p

我需要创建一个能够创建动态命令的类,我可以绑定到该类。我有一个带有插件的高度动态应用程序,开发人员只在后端创建插件,并从后端控制所有事情。前端是在另一个“远程”应用程序中创建的,该应用程序将后端作为DataContext。下面是一个示例(不是完整的示例),只是为了说明我想做什么:

<Window x:Class="WpfApplication7.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Button Command="{Binding PressMe}">PressMe</Button>
    </Grid>
</Window>


namespace WpfApplication7
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        TaskViewModel Model = new TaskViewModel();


        public MainWindow()
        {
            InitializeComponent();

            DataContext = Model;

            Model.AddCommand("PressMe", (o) => { Console.WriteLine("TEST"); });
        }
    }
}

压榨
命名空间WpfApplication7
{
/// 
///MainWindow.xaml的交互逻辑
/// 
公共部分类主窗口:窗口
{
TaskViewModel模型=新的TaskViewModel();
公共主窗口()
{
初始化组件();
DataContext=模型;
Model.AddCommand(“PressMe”,(o)=>{Console.WriteLine(“TEST”);});
}
}
}
所以问题是,如果XAML需要绑定可以查看的“定义良好”或“已知”属性,我如何创建类似的内容

我想到了一些TaskViewModel并实现了IExpando,但不知何故,当连接到IExpando方法时,反射并没有执行。有没有其他方法来做这样的事情

谢谢
Martin

与往常一样,WPF中基于项的UI是使用和利用实现的,而不管每个项的视觉外观如何,也不管底层类的实际行为如何

在本例中,您正在查找命令的动态集合:

// This class is not fully implemented. Replace by your own DelegateCommand or
// Grab an ICommand implementation from any of the well known MVVM Frameworks out there.
// This only exists for the sake of the example.
public class Command : ICommand
{
    private readonly Action action;

    public string DisplayName { get; private set; }

    public bool CanExecute(object parameter)
    {
        return true;
    }

    public event EventHandler CanExecuteChanged;

    public void Execute(object parameter)
    {
        action();
    }

    public Command(string displayName, Action action)
    {
        this.action = action;
        this.DisplayName = displayName;
    }
}
视图模型:

public class ViewModel
{
    public ObservableCollection<Command> Commands { get; private  set; }

    public ViewModel()
    {
        Commands = new ObservableCollection<Command>();
    }

    // You will add commands at some point at runtime.
    public void AddSomeCommands()
    {
        Commands.Add(new Command("Command1", () => MessageBox.Show("This is Command1!")));
        Commands.Add(new Command("Command2", () => MessageBox.Show("This is Command2!!")));
        Commands.Add(new Command("Command3", () => MessageBox.Show("This is Command3!!!")));
        Commands.Add(new Command("Command4", () => MessageBox.Show("This is Command4!!!!")));
    }
}
代码隐藏:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        var vm = new ViewModel();
        vm.AddSomeCommands();

        this.DataContext = vm;
    }
}
结果:

编辑:

如果需要将这些命令绑定到热键,只需向命令添加属性:

public Key HotKey { get; set; }
然后在代码隐藏中添加如下内容:

foreach (var c in vm.Commands)
    this.InputBindings.Add(new KeyBinding(c, c.HotKey, ModifierKeys.None));

您的视图不应该知道您的ViewModel,您正在打破MVVM设计模式。您应该将命令用作ViewModel的属性,而不是动态创建它们。@MikeEason我不同意。从您编写
{Binding Anything}
的那一刻起,视图就已经“知道”了ViewModel。尽管不存在编译时耦合,但仍然存在一种耦合,没有这种耦合,任何东西都无法工作。总之,OP,您只是在寻找一个
可观察的集合
和一个
项控件
@HighCore,这是错误的。它根本不耦合。实际上,这是一个隐含的契约。视图绑定到“某物”,从而形成一个契约,它期望DataContext拥有该“某物”。它不知道(耦合)datacontext实际上是什么。ViewModel为该绑定契约提供了实现(或不提供,但绑定失败)。@Meirionhugh提供了一个隐式契约,必须满足该隐式契约才能使一切正常工作。如果我为soapweb服务创建一个接口,或者说一个WSDL,根据定义,这就是一个契约。如果中间的任何部分不遵守合同,那么什么都不起作用。我的观点是,将代码耦合到特定的ViewModel(或者,如果您更喜欢的话,也可以耦合到接口)是可以的,就像使用
{Binding Anything}
是可以的一样。我明白您的观点。问题是我无法使用某些项集合,因为这些命令不仅用于按钮,还用于键盘事件。所以我真的需要有一个方法,在那里我可以引用一个名字。事实上,我可以使用ObservaleCollection,但我还需要一种在{Binding}中使用名称的方法。
foreach (var c in vm.Commands)
    this.InputBindings.Add(new KeyBinding(c, c.HotKey, ModifierKeys.None));