2017-08-29 61 views
1

TreeView的资源中,我有一个HierarchicalDataTemplate也定义了上下文菜单样式。目标是能够以编程方式将MenuItem指定为图标名称作为其Tag,然后让前端显示正确的图标。仅在检查时出现WPF上下文菜单数据绑定图标

<StackPanel.ContextMenu> 
    <ContextMenu ItemsSource="{Binding MenuItems}"> 
     <ContextMenu.Resources> 
      <Style TargetType="{x:Type MenuItem}"> 
       <Setter Property="Icon"> 
        <Setter.Value> 
         <local:StringToIcon IconName="{Binding Tag, RelativeSource={RelativeSource AncestorType=MenuItem}}" /> 
        </Setter.Value> 
       </Setter> 
      </Style> 
     </ContextMenu.Resources> 
    </ContextMenu> 
</StackPanel.ContextMenu> 

StringToIcon是另一种控制,对于测试,看起来就像这样。它由依赖属性IconName支持。

<UserControl x:Class="MyApp.Components.StringToIcon" 
      ... 
      Name="StringIconControl"> 
    <Image DataContext="{Binding ElementName=StringIconControl}"> 
     <Image.Style> 
      <Style TargetType="{x:Type Image}"> 
       <Style.Triggers> 
        <DataTrigger Binding="{Binding IconName}" Value="Refresh"> 
         <Setter Property="Source" Value="{StaticResource IconRefresh}"/> 
        </DataTrigger> 
       </Style.Triggers> 
      </Style> 
     </Image.Style> 
    </Image> 
</UserControl> 

IconRefresh简直是一个全球可用的资源:

<BitmapImage x:Shared="False" x:Key="IconRefresh" UriSource="pack://application:,,,/Resources/Icons/refresh.png" /> 

当启动应用程序,没有上下文菜单刷新图标出现。他们都是空白的。我得到绑定错误,我带领相信是由于上下文菜单可视化树不是:

无法为参照结合找到源“的RelativeSource FindAncestor,AncestorType =” System.Windows.Controls .MenuItem',AncestorLevel ='1''。 BindingExpression:路径=标签;的DataItem = NULL;目标元素是'StringToIcon'(Name ='StringIconControl');目标属性是'IconName'(类型'String')

但是,当使用Snoop检查菜单时,所有的绑定和依赖项属性都是正确的。以这种方式检查后,检查到的刷新图标奇迹般地出现,好像它迫使绑定重新评估一样。您可以逐个执行此操作,以显示此图标的每个实例。

如何解决这个似乎在这里发生的惰性绑定?或者还有其他什么玩法?我看到另一篇文章,建议将菜单数据上下文附加到可视树中的,但我没有看到在这种情况下会出现什么内容。

回答

0

最终的解决方案,结合问题是使一个新的类来保存菜单项目的详情:

public class BindableMenuItem 
{ 
    public BindableMenuItem(string name, ICommand command) 
    { 
     this.Name = name; 
     this.Command = command; 
    } 
    public string Name { get; set; } 
    public ICommand Command { get; set; } 
    public string IconName { get; set; } 
    public ObservableCollection<BindableMenuItem> Children { get; set; } 
} 

然后将其捆绑起来,以菜单项的样式如下:

<Style TargetType="MenuItem"> 
    <Setter Property="Header" Value="{Binding Name}" /> 
    <Setter Property="Command" Value="{Binding Command}" /> 
    <Setter Property="ItemsSource" Value="{Binding Children}" /> 
    <Setter Property="Icon"> 
     <Setter.Value> 
      <local:StringToIcon IconName="{Binding IconName}" /> 
     </Setter.Value> 
    </Setter> 
</Style> 

大概这是有效的,因为绑定不依赖于在可视树中存在相对源,而是它有一个具体的模型类来使用。

但是,上述关于多样式实例仍然存在问题。我会为此发布另一个问题。