2013-05-08 45 views
0

希望这个问题不是太笼统,但是我刚开始使用WPF,而且我对此感到头痛。使用MVVM动态创建UI控件的上下文菜单命令

我正在开发一个使用动态创建控件的应用程序。然而,目前我无法弄清楚如何使命令创建并向当前窗口添加更多控件,因为这些命令仅在ViewModel中创建时无法看到视图。但是我无法将所有内容都保存在XAML中,因为除了一些最初为空的堆栈面板之外的所有控件都是动态的。尽管如此,我觉得我很想念一些简单的东西。

所以我在这里有约束力

<MenuItem Header="LabelMenuItem" Command="{Binding Path=SpawnLabel}"/> 

在这里,我有命令

public ICommand SpawnLabel { get { return new DelegateCommand(OnSpawnLabel); } } 

委托命令类似于这里定义的继电器命令。

public class DelegateCommand : ICommand 
    { 
     private readonly Action _command; 
     private readonly Func<bool> _canExecute; 
     public event EventHandler CanExecuteChanged 
     { 
      add { CommandManager.RequerySuggested += value; } 


     remove { CommandManager.RequerySuggested -= value; } 
    } 

    public DelegateCommand(Action command, Func<bool> canExecute = null) 
    { 
     if (command == null) 
      throw new ArgumentNullException(); 
     _canExecute = canExecute; 
     _command = command; 
    } 

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

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

} 

这个作品在视图模型,但我无法弄清楚如何在地球上,以使其在视图中工作(或倾诉的观点没有打破MVVM原则),这样我就可以使用真正改变UI当前在c#中创建的控件。

目前,当我这样做时,我得到一个BindingExpression路径错误,这是有道理的,但我无法弄清楚如何绑定它在视图中查找命令。

回答

0

你间接地与UI通过事件进行通信,如果你改变你开除PropertyChanged的属性,UI将更新的绑定,如果你改变一个集合你火CollectionChanged,并增加了新的控制或旧的清除。

的重要接口INotifyPropertyChangedINotifyCollectionChanged,只需绑定一个ItemsControl(通过ItemsSource)在您的视图模型的ObservableCollection<T>并添加到集合中的命令(您可能需要使用ItemsControl.ItemTemplate指定查看您视图模型,取决于你使用的MVVM框架)。

+0

所以我会在ViewModel中执行命令代码,然后onExecute会触发在视图中触发的CollectionChanged,然后我可以添加新的UI元素? – Smeasum 2013-05-08 21:54:17

+0

@Smeasum:不,您只需向ObservableCollection中添加一个项目,然后在内部启动该事件,其中ItemsControl将创建指定为ItemTemplate的内容或者为[隐式指定的项目类型](http://stackoverflow.com/questions/5644392/conditional-list-itemtemplate-or-datatemplate-in-wpf/5644414#5644414)。如果您搜索SO或网络,有很多这样的例子,另见[MSDN](http://msdn.microsoft.com/en-us/library/ms752347.aspx#binding_to_collections)。 – 2013-05-08 22:08:00