使用父级的DataContext(WPF - 动态菜单命令绑定)

时间:2009-06-15 20:02:40

标签: c# wpf dynamic menu commandbinding

我查看了这个网站和谷歌,解决方案对我不起作用。

我在UserControl的ViewModel上有一个命令。好吧,usercontrol有一个绑定到ObservableCollection的ItemsControl。在ItemsControl.ItemTemplate的DataTemplate中,我有一个按钮,我想使用该命令。我无法绑定命令,因为在DataTemplate中,datacontext不是ViewModel而是ObservableCollection的项目。

问题是:如果丢失了父datacontext,如何将按钮绑定到命令?

我认为这需要一个简单的解决方案,因为我认为这是一个常见的问题。

想象一下这个场景:

您有一个带有observableCollection的ListBox项作为ItemsSource,因此您在ListBox中为集合中的每个元素使用了一个datatemplate。好吧,您想删除所选项目,并在该行的每一行中放置一个按钮。 ¿你怎么做的?

在MVP中,我可以在按钮的点击事件中执行此操作:

Button but = e.Source as Button;

if (but != null)
      Presenter.ActualNote = but.DataContext as Note;

简而言之。您将行的datacontext(所选项目)发送给演示者。

但是,我怎么能用mvvm方式呢?因为我需要使用命令,但我无法将命令分配给按钮,因为该按钮对ViewModel(命令所在的位置)一无所知。

正如您所看到的,按钮必须存在于datatemplate中,然后datacontext不再是ViewModel ....这就是为什么我需要访问父的DataContext,以访问该命令。

我希望你能更好地理解我的问题。

谢谢。

4 个答案:

答案 0 :(得分:89)

使用下面的绑定作为按钮的命令:

{Binding DataContext.CommandName, 
         RelativeSource={RelativeSource FindAncestor, 
                         AncestorType={x:Type MyUserControl}}}

这将告诉它找到你的UserControl并使用它的DataContext。

答案 1 :(得分:5)

如果你想要一个破坏性的MVVM解决方案,那么在按钮上设置Tag =“{Binding}”并处理Click事件。在事件处理程序中,在ViewModel上调用该命令。

答案 2 :(得分:3)

那么,那么修改数据项类以使其具有引用整个模型视图的属性呢?

如果您的ItemsSource类型为ObservableCollection<DataItem>,则修改DataItem类型,如下所示:

public class DataItem
{
    public BusinessObject Value { get; set; }

    private ModelView modelView;

    public ModelView ModelView
    {
        get
        {
            return modelView;
        }
    }

    public DataItem(ModelView modelView)
    {
        this.modelView = modelView;
    }
}

答案 3 :(得分:2)

RelativeSource有效,但我不认为让控件在彼此的属性中徘徊是正确的。奇怪的是,放置在项目视图中的按钮使用外部数据源而不是绑定项目执行某些操作。您可能需要查看程序代码的设计。