通过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