在我的项目中我使用了wpf + prism。在一个视图中,我必须在上下文菜单中调用一个命令,该命令被定义到viewmodel类中。这是视图:
<UserControl x:Class="GrigoLync.Modules.LyncClient.Contatti.ContattiView"
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:infr="clr-namespace:GrigoLync.infrastructure.Model.Lync;assembly=GrigoLync.infrastructure"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
</Grid.RowDefinitions>
<Label Grid.Column="0" Grid.Row="0" FontSize="12" Margin="5">Contatti</Label>
<TreeView x:Name="groupTreeView" Margin="10" ItemsSource="{Binding GruppiLync}" >
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Path=ContattiLync}">
<TextBlock Text="{Binding Path=Nome}" />
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Uri}" Tag="{Binding}">
<TextBlock.ContextMenu>
<ContextMenu>
<MenuItem Header ="Invia messaggio istantaneo"
Command="{Binding PlacementTarget.Tag.SendInstantMessageCommand,RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContextMenu}, diag:PresentationTraceSources.TraceLevel=High}"/>
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</Grid>
以下是viewmodel类:
[Export(typeof(ContattiViewModel))]
[PartCreationPolicy(CreationPolicy.Shared)]
public class ContattiViewModel : NotificationObject
{
private readonly ILyncClientService lyncClientService;
private readonly IRegionManager regionManager;
private readonly IEventAggregator eventAggregator;
private List<GruppoLync> gruppiLync;
private ICommand sendInstantMessageCommand;
[ImportingConstructor]
public ContattiViewModel(ILyncClientService lyncClientService, IRegionManager regionManager, IEventAggregator eventAggregator)
{
if (lyncClientService == null)
{
throw new ArgumentNullException("lyncClientService");
}
if (regionManager == null)
{
throw new ArgumentNullException("regionManager");
}
if (eventAggregator == null)
{
throw new ArgumentNullException("eventAggregator");
}
this.lyncClientService = lyncClientService;
this.regionManager = regionManager;
this.eventAggregator = eventAggregator;
this.gruppiLync = lyncClientService.elencoGruppiLync();
this.sendInstantMessageCommand = new DelegateCommand<object>(this.SendInstantMessage);
//groupTreeView.DataItems = this.gruppiLync;
}
public ICommand SendInstantMessageCommand { get { return this.sendInstantMessageCommand; } }
public List<GruppoLync> GruppiLync
{
get
{
return this.gruppiLync;
}
}
private void SendInstantMessage(object aContattoLync)
{
//This point is not executed!
}
}
}
当我从用户界面中选择菜单项“Invia Messaggio istantaneo”时,命令不会被调用,此点不会被执行
可以帮我吗?!!!!
这是GruppoLync类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Collections.ObjectModel;
namespace GrigoLync.infrastructure.Model.Lync
{
public class GruppoLync : INotifyPropertyChanged
{
private string nome;
public string Nome
{
get { return nome; }
set { nome = value;
OnPropertyChanged(new PropertyChangedEventArgs("Nome"));
}
}
private ObservableCollection<ContattoLync> contattiLync;
public ObservableCollection<ContattoLync> ContattiLync
{
get { return contattiLync; }
set
{
contattiLync = value;
OnPropertyChanged(new PropertyChangedEventArgs("ContattiLync"));
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(PropertyChangedEventArgs e)
{
if (PropertyChanged != null)
PropertyChanged(this, e);
}
public GruppoLync(string nome, ObservableCollection<ContattoLync> contattiLync)
{
Nome = nome;
ContattiLync = contattiLync;
}
}
}
这是ContattoLync类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
using Microsoft.Practices.Prism.Commands;
namespace GrigoLync.infrastructure.Model.Lync
{
public class ContattoLync
{
public string Uri { get; set; }
public string Stato { get; set; }
}
}
我还报告了绑定的跟踪日志:
System.Windows.Data Warning: 54 : Created BindingExpression (hash=37997052) for Binding (hash=17879784)
System.Windows.Data Warning: 56 : Path: 'PlacementTarget.Tag.SendInstantMessageCommand'
System.Windows.Data Warning: 58 : BindingExpression (hash=37997052): Default mode resolved to OneWay
System.Windows.Data Warning: 59 : BindingExpression (hash=37997052): Default update trigger resolved to PropertyChanged
System.Windows.Data Warning: 60 : BindingExpression (hash=37997052): Attach to System.Windows.Controls.MenuItem.Command (hash=47163810)
System.Windows.Data Warning: 64 : BindingExpression (hash=37997052): RelativeSource (FindAncestor) requires tree context
System.Windows.Data Warning: 63 : BindingExpression (hash=37997052): Resolve source deferred
System.Windows.Data Warning: 54 : Created BindingExpression (hash=18607377) for Binding (hash=17879784)
System.Windows.Data Warning: 56 : Path: 'PlacementTarget.Tag.SendInstantMessageCommand'
System.Windows.Data Warning: 58 : BindingExpression (hash=18607377): Default mode resolved to OneWay
System.Windows.Data Warning: 59 : BindingExpression (hash=18607377): Default update trigger resolved to PropertyChanged
System.Windows.Data Warning: 60 : BindingExpression (hash=18607377): Attach to System.Windows.Controls.MenuItem.Command (hash=32025604)
System.Windows.Data Warning: 64 : BindingExpression (hash=18607377): RelativeSource (FindAncestor) requires tree context
System.Windows.Data Warning: 63 : BindingExpression (hash=18607377): Resolve source deferred
System.Windows.Data Warning: 65 : BindingExpression (hash=37997052): Resolving source
System.Windows.Data Warning: 68 : BindingExpression (hash=37997052): Found data context element: <null> (OK)
System.Windows.Data Warning: 71 : Lookup ancestor of type ContextMenu: queried ContextMenu (hash=46231978)
System.Windows.Data Warning: 70 : RelativeSource.FindAncestor found ContextMenu (hash=46231978)
System.Windows.Data Warning: 76 : BindingExpression (hash=37997052): Activate with root item ContextMenu (hash=46231978)
System.Windows.Data Warning: 106 : BindingExpression (hash=37997052): At level 0 - for ContextMenu.PlacementTarget found accessor DependencyProperty(PlacementTarget)
System.Windows.Data Warning: 102 : BindingExpression (hash=37997052): Replace item at level 0 with ContextMenu (hash=46231978), using accessor DependencyProperty(PlacementTarget)
System.Windows.Data Warning: 99 : BindingExpression (hash=37997052): GetValue at level 0 from ContextMenu (hash=46231978) using DependencyProperty(PlacementTarget): <null>
System.Windows.Data Warning: 104 : BindingExpression (hash=37997052): Item at level 1 is null - no accessor
System.Windows.Data Warning: 101 : BindingExpression (hash=37997052): Replace item at level 2 with {NullDataItem}
System.Windows.Data Warning: 78 : BindingExpression (hash=37997052): TransferValue - got raw value {DependencyProperty.UnsetValue}
System.Windows.Data Warning: 86 : BindingExpression (hash=37997052): TransferValue - using fallback/default value <null>
System.Windows.Data Warning: 87 : BindingExpression (hash=37997052): TransferValue - using final value <null>
System.Windows.Data Warning: 65 : BindingExpression (hash=18607377): Resolving source
System.Windows.Data Warning: 68 : BindingExpression (hash=18607377): Found data context element: <null> (OK)
System.Windows.Data Warning: 71 : Lookup ancestor of type ContextMenu: queried ContextMenu (hash=64235)
System.Windows.Data Warning: 70 : RelativeSource.FindAncestor found ContextMenu (hash=64235)
System.Windows.Data Warning: 76 : BindingExpression (hash=18607377): Activate with root item ContextMenu (hash=64235)
System.Windows.Data Warning: 105 : BindingExpression (hash=18607377): At level 0 using cached accessor for ContextMenu.PlacementTarget: DependencyProperty(PlacementTarget)
System.Windows.Data Warning: 102 : BindingExpression (hash=18607377): Replace item at level 0 with ContextMenu (hash=64235), using accessor DependencyProperty(PlacementTarget)
System.Windows.Data Warning: 99 : BindingExpression (hash=18607377): GetValue at level 0 from ContextMenu (hash=64235) using DependencyProperty(PlacementTarget): <null>
System.Windows.Data Warning: 104 : BindingExpression (hash=18607377): Item at level 1 is null - no accessor
System.Windows.Data Warning: 101 : BindingExpression (hash=18607377): Replace item at level 2 with {NullDataItem}
System.Windows.Data Warning: 78 : BindingExpression (hash=18607377): TransferValue - got raw value {DependencyProperty.UnsetValue}
System.Windows.Data Warning: 86 : BindingExpression (hash=18607377): TransferValue - using fallback/default value <null>
System.Windows.Data Warning: 87 : BindingExpression (hash=18607377): TransferValue - using final value <null>
答案 0 :(得分:2)
那是因为ContextMenus位于一个单独的逻辑树上 这意味着它们不会“继承”它们所依赖的元素的DataContext。
解决方法是:
<TextBlock Tag="{Binding}"> <!-- You may have to use RelativeSource on this Binding, depending on which DataContext you're trying to reach -->
<TextBlock.ContextMenu>
<ContextMenu>
<MenuItem Header="Name of the item"
Command="{Binding PlacementTarget.Tag.MyCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContextMenu}" />
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
这将在此MenuItem的ContextMenu中的PlacementTarget标记上获取MyCommand。
PlacementTarget poiting到TextBlock,其Tag指向您视图的DataContext。
答案 1 :(得分:0)
检查menuitem的datacontext以查看它是否正确
答案 2 :(得分:0)
我认为使用绑定“RelativeSource = {RelativeSource FindAncestor ...”有点奇怪,你宁愿直接绑定到项目集的属性作为你的hierchical datatemplate的datacontext。
答案 3 :(得分:0)
我解决了问题!!!!
<TreeView x:Name="groupTreeView" Margin="10" ItemsSource="{Binding GruppiLync}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Path=ContattiLync}">
<TextBlock Text="{Binding Path=Nome}" />
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Uri}"
Tag="{Binding DataContext, RelativeSource={RelativeSource AncestorType=TreeView}}">
<TextBlock.ContextMenu>
<ContextMenu DataContext="{Binding PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
<MenuItem Header ="Invia messaggio istantaneo"
Command="{Binding SendInstantMessageCommand, diag:PresentationTraceSources.TraceLevel=High}"
CommandParameter="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}}"/>
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
感谢All !!!