仅在检查时才会显示WPF上下文菜单数据绑定图标

时间:2017-08-29 15:41:54

标签: c# wpf data-binding contextmenu

TreeView资源中,我有一个HierarchicalDataTemplate,它还定义了上下文菜单样式。目的是能够以编程方式定义MenuItem指定图标名称为Tag,然后让前端显示正确的图标。

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

启动应用程序时,不会显示任何上下文菜单刷新图标。他们都是空白的。我遇到了绑定错误,我认为这是因为上下文菜单不在可视化树中:

  

无法找到使用引用绑定的来源&#39; RelativeSource FindAncestor,AncestorType =&#39; System.Windows.Controls.MenuItem&#39;,AncestorLevel =&#39; 1&#39;&#39;。 BindingExpression:路径=标签;的DataItem = NULL;目标元素是&#39; StringToIcon&#39; (名称=&#39; StringIconControl&#39);目标属性是&#39; IconName&#39; (键入&#39; String&#39;)

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

如何解决这里似乎发生的这种懒惰绑定?或者还有别的东西在玩吗?我看到另一篇文章建议将菜单数据上下文附加到可视树中 的内容,但我不知道在这个实例中会出现什么。

1 个答案:

答案 0 :(得分: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>

可能这是有效的,因为绑定不依赖于可视化树中存在相对源,而是具有要使用的具体模型类。

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