通过mvvm无法访问嵌套wpf项目命令

比方说,我有一个虚拟的WPF应用程序(面向MVVM)。 我的主窗口包含我创建的自定义列表,并且列表包含自定义项目。 该项目有一个图像按钮,我希望按钮命令是我在视图模型中获得的命令。 视图模型绑定到主窗口。 我该怎么做 ?

我附上了虚拟项目(在此处下载:http://www.2shared.com/file/qmO3E5rx/NestedCommand.html或在这里:http://www.multiupload.nl/KCFLSKAIH0),

但如果您不想下载它,代码如下所示:

MainWindow XAML:

<Window x:Class="WpfApplication2.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:Application="clr-namespace:WpfApplication2"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <Application:List x:Name="myList" DataContext="{Binding}" />
</Grid>

MainWindow Code-Behind:

        public MainWindow()
    {
        InitializeComponent();
        CharacterViewModel viewModel = new CharacterViewModel();
        this.myList.ItemsList.ItemsSource = viewModel.Model.Powers;
    }

列表XAML:

<UserControl x:Class="WpfApplication2.List"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:Application="clr-namespace:WpfApplication2"
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">
<Grid>
    <ListView x:Name="ItemsList" ItemsSource="{Binding Path=Name}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <Application:Item x:Name="myItem" />
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</Grid>

项目XAML:

<UserControl x:Class="WpfApplication2.Item"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" 
         d:DesignHeight="50" d:DesignWidth="50">
<Grid>
    <Button x:Name="ButtonImage" Command="**????????**">
        <Button.Template>
            <ControlTemplate>
                <Border HorizontalAlignment="Center" VerticalAlignment="Center" >
                    <Image Width="50" Height="50" Source="/WpfApplication2;component/Images/Jellyfish.jpg"/>
                </Border>
            </ControlTemplate>
        </Button.Template>
    </Button>
</Grid>

ViewModel代码:

    public class CharacterViewModel : ObjectBase
{
    public Character Model { get; private set; }
    public DelegateCommand<object> RemoveCommand { get; private set; }

    public CharacterViewModel()
        : this(Character.Create())
    {
    }

    public CharacterViewModel(Character model)
    {
        Model = model;
        RemoveCommand = new DelegateCommand<object>(RemoveCommand_Execute, RemoveCommand_CanExecute, "Save");
    }

    void RemoveCommand_Execute(object arg)
    {
        Model.Powers.Clear();
        MessageBox.Show(string.Format("{0} character powers removed.", Model.Name));
    }

    bool RemoveCommand_CanExecute(object arg)
    {
        return Model.Name != string.Empty;
    }
}

型号:

public class Character : ObjectBase
{
    string _Name = string.Empty;
    ObservableCollection<string> _Powers = new ObservableCollection<string>();

    public string Name
    {
        get { return _Name; }
        set
        {
            if (_Name == value)
                return;

            _Name = value;
            OnPropertyChanged("Name");
        }
    }

    public ObservableCollection<string> Powers
    {
        get { return _Powers; }
    }

    public static Character Create()
    {
        Character hero = new Character()
        {
            Name = "Superman",
        };

        hero.Powers.Add("Flight");
        hero.Powers.Add("Strength");
        hero.Powers.Add("X-Ray Vision");

        return hero;
    }
}

框架代码:

public class DelegateCommand<T> : ICommand
{
    public DelegateCommand(Action<T> execute) : this(execute, null) { }

    public DelegateCommand(Action<T> execute, Predicate<T> canExecute) : this(execute, canExecute, "") { }

    public DelegateCommand(Action<T> execute, Predicate<T> canExecute, string label)
    {
        _Execute = execute;
        _CanExecute = canExecute;

        Label = label;
    }

    readonly Action<T> _Execute = null;
    readonly Predicate<T> _CanExecute = null;

    public string Label { get; set; }

    public void Execute(object parameter)
    {
        _Execute((T)parameter);
    }

    public bool CanExecute(object parameter)
    {
        return _CanExecute == null ? true : _CanExecute((T)parameter);
    }

    public event EventHandler CanExecuteChanged
    {
        add
        {
            if (_CanExecute != null)
                CommandManager.RequerySuggested += value;
        }
        remove
        {
            if (_CanExecute != null)
                CommandManager.RequerySuggested -= value;
        }
    }
}

public abstract class ObjectBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected internal void OnPropertyChanged(string propertyName)
    {
        if (this.PropertyChanged != null)
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

感谢您的帮助


ListItem的DataContext是它绑定到的项目,而不是您要查找的项目。 您正在查找UserControl的DataContext,并获得您需要使用ElementName显式引用UserControl或使用RelativeSource绑定来浏览可视化树。 RelativeSource可能是最好的解决方案,因为它引用了控件本身,所以需要在绑定的Path中指定要查找DataContext上的RemoveCommand成员 - 就​​像Path=DataContext.RemoveCommand 。 看下面的完整例子。

XAML:

<Grid DataContext="{Binding}"> <!-- Set the binding for the DataContext of the control and all of its children -->
    <ListView ItemsSource="{Binding Path=Model.Powers}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <!-- Use RelativeSource to access the Grid control and then get its DataContext -->
                <Button Command="{Binding Path=DataContext.RemoveCommand, RelativeSource={RelativeSource AncestorType=Grid}}">
                    <Border HorizontalAlignment="Center" VerticalAlignment="Center" >
                        <Image Width="50" Height="50" Source="/WpfApplication2;component/Images/Jellyfish.jpg"/>
                    </Border>
                </Button>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</Grid>
链接地址: http://www.djcxy.com/p/56143.html

上一篇: Cant access nested wpf item command by mvvm

下一篇: WPF Button key down modifies click command in XAML/MVVM