从ItemsControl的ItemTemplate.DataTemplate中访问ViewModel实例

时间:2014-02-27 23:58:55

标签: mvvm binding command viewmodel

我在单独的文件(Styles.xaml)中定义了数据模板。 Page有一个ViewModel实例(我使用的是MVVM模式)。 我的视图模型包含我试图通过数据模板绑定的命令。

我如何访问它?

我的绑定无法解析

ElementNameRelativeSource

Page Xaml:

xmlns:partial="clr-namespace:PhoneApp7.Partial"

...
<phone:PhoneApplicationPage.DataContext>
    <viewModel:DynamicViewModel />
</phone:PhoneApplicationPage.DataContext>
...

<ItemsControl x:Name="ItemsControl" ItemsSource="{Binding Items}">
    <ItemsControl.ItemTemplate>
       <DataTemplate>
             <partial:DoItItemTemplate />
        </DataTemplate>
       </ItemsControl.ItemTemplate>
</ItemsControl>

查看型号:

public class DynamicViewModel
{
    public ObservableCollection<string> Items
    {
        get
        {
            return new ObservableCollection<string>
            {
                "item 1",
                "item 2",
                "item 2",
            };
        }
    }

    public RelayCommand<string> DoIt { get; set; }

    public DynamicViewModel()
    {
        DoIt = new RelayCommand<string>(OnDoIt);
    }

    private void OnDoIt(string args)
    {
        MessageBox.Show(string.Format("Yay! {0}", args));
    }
}

项目用户控制Xaml

<UserControl x:Class="PhoneApp7.Partial.DoItItemTemplate"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <Button Content="{Binding}" Command="{Binding DataContext.DoIt, ElementName=ItemsControl}" CommandParameter="{Binding}"></Button>

</UserControl>

您可以通过以下链接找到完整的示例: https://dl.dropboxusercontent.com/u/83972129/binding_issue.zip

2 个答案:

答案 0 :(得分:1)

这个问题(IMHO)最干净的解决方案是给UserControl一个Command依赖属性,并让Button的Command属性绑定到该属性。

然后,您可以通过使用ElementName = ItemsControl绑定到DataContext.DoIt,从MainPage中将UserControl的新Command属性绑定到所需的命令。

如果情况需要,它还可以提供一些额外的灵活性来绑定到其他命令,而不是硬编码命令绑定到模板本身。

用户控件:

public partial class DoItItemTemplate : UserControl
{
    // ...

    private static void CommandChangedCallback(...)
    {
        DoItItemTemplate owner = (DoItItemTemplate)d;
        owner.CommandChanged((ICommand)e.OldValue, (ICommand)e.NewValue);
    }

    private void CommandChanged(ICommand oldValue, ICommand newValue)
    {

    }

    public static readonly DependencyProperty CommandProperty = DependencyProperty.Register(...)
    public ICommand Command
    {
        get { return (ICommand)GetValue(CommandProperty); }
        set { SetValue(CommandProperty, value); }
    }

    // ...

}


<UserControl x:Class="PhoneApp7.Partial.DoItItemTemplate"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             x:Name="root">

    <Button Content="{Binding}"
            Command="{Binding Path=Command, ElementName=root}"
            CommandParameter="{Binding}"></Button>

</UserControl>

在主页面中:

       <ItemsControl x:Name="ItemsControl" ItemsSource="{Binding Items}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <partial:DoItItemTemplate Command="{Binding DataContext.DoIt, ElementName=ItemsControl}" />
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>

答案 1 :(得分:0)

如果需要,你可以使用类助手;如果您需要在许多控件或数据模板中使用此命令,它将非常有用。