31

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

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

问题是:如果丢失了父数据上下文,如何将按钮绑定到命令?

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

想象一下这个场景:

您有一个带有 observableCollection 作为 ItemsSource 的 ListBox 项,因此您在 ListBox 内为集合中的每个元素使用一个数据模板。好吧,您想删除选定的项目,并在该作业的每一行中放置一个按钮。你是怎样做的?

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

Button but = e.Source as Button;

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

简而言之。您将行(所选项目)的数据上下文发送给演示者。

但是,我怎样才能以 mvvm 方式做到这一点?因为我需要使用命令,但我无法将命令分配给按钮,因为按钮对 ViewModel (命令所在的位置)一无所知。

如您所见,按钮必须存在于数据模板中,然后数据上下文不再是 ViewModel.... 这就是为什么我需要访问父级的 DataContext 才能访问命令的原因。

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

谢谢你。

4

4 回答 4

91

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

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

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

于 2009-06-15T20:09:58.817 回答
5

如果您想要一个肮脏的、破坏 MVVM 的解决方案,请在按钮上设置 Tag="{Binding}" 并处理 Click 事件。在事件处理程序中,调用 ViewModel 上的命令。

于 2009-06-15T21:10:13.650 回答
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;
    }
}
于 2009-06-17T06:07:28.450 回答
2

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

于 2009-06-15T20:58:09.373 回答