1

在我的项目中,我使用了 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>

以下是视图模型类:

 [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>
4

4 回答 4

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 指向 TextBlock,其 Tag 指向视图的 DataContext。

于 2012-08-21T08:51:29.883 回答
1

我解决问题!!!!

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

谢谢大家!!!

于 2012-08-22T06:30:14.347 回答
0

检查菜单项的数据上下文以查看其是否正确

于 2012-08-21T08:39:52.360 回答
0

我认为使用“RelativeSource = {RelativeSource FindAncestor ...”绑定有点奇怪,您宁愿直接绑定到项目集的属性作为分层数据模板的数据上下文。

于 2012-08-21T08:39:55.197 回答