我需要将Command
和CommandParameter
绑定到位于ContextMenu
内的WPF MenuItem
ItemsControl.ItemTemplate
内的两个不同的类。问题是ContextMenu
有一个单独的可视树而不是窗口的其余部分。我在.NET 4.0+中使用它,但无法找到适用于.NET 3.5的解决方法。
注意:即使是运行中的.NET 4.0+解决方法也可以在运行时运行,但会破坏Visual Studio 2013 Designer和Blend Designer。
如何将CommandParameter
绑定到单个CustomerViewModel
并将Command
绑定到.NET 3.5中的EditCustomersController
?
查看
<Window
x:Class="MvvmLight1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MVVM Light Application"
DataContext="{Binding EditCustomers, Source={StaticResource Locator}}">
<ItemsControl
x:Name="rootElement"
ItemsSource="{Binding Customers}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock
Text="{Binding Name}">
<TextBlock.ContextMenu>
<ContextMenu
PlacementTarget="{Binding ElementName=myTextBlock}">
<MenuItem
Header="Capitalize Using RelativeSource (Does not work)"
CommandParameter="{Binding}"
Command="{Binding
Path=DataContext.CapitalizeCommand,
RelativeSource={RelativeSource
FindAncestor,
AncestorType={x:Type Window}}}" />
<MenuItem
Header="Lowercase Using RelativeSource (Does not work)"
CommandParameter="{Binding}"
Command="{Binding
Path=DataContext.LowercaseCommand,
RelativeSource={RelativeSource
FindAncestor,
AncestorType={x:Type Window}}}" />
<MenuItem
Header="Capitalize Using Source (Only works in .NET 4.0+)"
CommandParameter="{Binding}"
Command="{Binding
Path=DataContext.CapitalizeCommand,
Source={x:Reference Name=rootElement}}" />
<MenuItem
Header="Lowercase Using Source (Only works in .NET 4.0+)"
CommandParameter="{Binding}"
Command="{Binding
Path=DataContext.LowercaseCommand,
Source={x:Reference Name=rootElement}}" />
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Window>
控制器
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using System.Collections.Generic;
using System.Windows.Input;
public class EditCustomersController : ViewModelBase
{
public EditCustomersController()
{
this.CapitalizeCommand = new RelayCommand<CustomerViewModel>(this.Capitalize);
this.LowercaseCommand = new RelayCommand<CustomerViewModel>(this.Lowercase);
var c = new List<CustomerViewModel>();
c.Add(new CustomerViewModel("Fred"));
c.Add(new CustomerViewModel("Bob"));
c.Add(new CustomerViewModel("Sue"));
c.Add(new CustomerViewModel("Sally"));
this.Customers = c;
}
public IEnumerable<CustomerViewModel> Customers { get; set; }
public ICommand CapitalizeCommand { get; private set; }
public ICommand LowercaseCommand { get; private set; }
private void Capitalize(CustomerViewModel customer)
{
customer.Name = customer.Name.ToUpper();
}
private void Lowercase(CustomerViewModel customer)
{
customer.Name = customer.Name.ToLower();
}
}
视图模型
using GalaSoft.MvvmLight;
public class CustomerViewModel : ViewModelBase
{
private string name;
public CustomerViewModel(string name)
{
this.name = name;
}
public string Name
{
get
{
return this.name;
}
set
{
this.Set(() => this.Name, ref this.name, value);
}
}
}
答案 0 :(得分:0)
通过将ContextMenu
移动到资源并通过使用DataContext
属性传递顶级Tag
,使其适用于所有.NET版本。在ContextMenu
MenuItem
内,我可以使用CustomerViewModel
和{Binding}
使用EditCustomersController
和{{1}的绑定访问当前Tag
}}
查看
RelativeSource