繁体   English   中英

努力用控件模板化WPF MenuItem的Icon

[英]Struggling to template a WPF MenuItem's Icon with control

从上一个问题开始 ,我正在努力使用一个具有基于字符串依赖项属性插入图标图像的控件来对MenuItemIcon进行样式设置。

最初,我以:

<ContextMenu ItemsSource="{Binding MenuItems}">
    <ContextMenu.Resources>
        <Style TargetType="MenuItem">
            ...
            <Setter Property="Icon">
                <local:StringToIcon IconName="{Binding IconName}" />
            </Setter>
        </Style>
    </ContextMenu.Resources>
</ContextMenu>

可以预见的效果是,由于实例是共享的,因此仅显示菜单中的一个图标(通常是最后一个)。

然后,我尝试了非共享资源方法:

<ContextMenu ItemsSource="{Binding MenuItems}">
    <ContextMenu.Resources>
        <local:StringToIcon x:Key="MenuIcon" x:Shared="False" IconName="{Binding IconName}" />
        <Style TargetType="MenuItem">
            ...
            <Setter Property="Icon" Value="{StaticResource MenuIcon} />
        </Style>
    </ContextMenu.Resources>
</ContextMenu>

这没有效果。 它没有向我提供x:Shared在Intellisense中x:Shared ,所以我想知道这是否是无效的属性。

出于绝望,我把这个东西扔进了一个模板:

<Setter Property="Icon">
    <Setter.Value>
        <ContentControl>
            <ContentControl.Template>
                <ControlTemplate>
                    <local:StringToIcon IconName="{Binding IconName}" />
                </ControlTemplate>
            </ContentControl.Template>
        </ContentControl>
    </Setter.Value>
</Setter>

同样,没有效果。 目前,我的StringToIcon看起来像这样,用单个图像进行硬编码以检查问题是否就在这里。 (还是?)

<UserControl x:Class="RAP.Admin3.Components.StringToIcon"
    ...
>
    <Image DataContext="{Binding ElementName=StringIconControl}" Source="pack://application:,,,/Resources/Icons/lorry.png"/>
</UserControl>

如何将这些令人毛骨悚然的东西用作模板并允许多次使用? 这可能是我忽略的基本知识。

我看过各种类似的问题,并且大多数问题似乎都可以通过非共享资源方法获得成功。

编辑 :让我根据要求添加更多代码。 我提出了对该问题的最小复制:

上下文菜单是TreeView资源的一部分。

<UserControl x:Class="MyApp.ItemHierarchy"
             ...
             Name="ItemHierarchyControl">
    <Grid>
        <TreeView ItemsSource="{Binding ElementName=ItemHierarchyControl, Path=Items}">
            <TreeView.Resources>
                <HierarchicalDataTemplate DataType="{x:Type local:HierarchyItem}" ItemsSource="{Binding Subitems}">
                    <StackPanel Orientation="Horizontal" Margin="0,1,4,1">
                        <TextBlock Text="My text" VerticalAlignment="Center" />
                        <StackPanel.ContextMenu>
                            <ContextMenu ItemsSource="{Binding MenuItems}">
                                <ContextMenu.Resources>
                                    <local:StringToIcon x:Key="MenuIcon" x:Shared="False" IconName="{Binding IconName}" />
                                    <Style TargetType="MenuItem">
                                        <Setter Property="Header" Value="{Binding Path=Name}" />
                                        <Setter Property="Icon" Value="{StaticResource MenuIcon}" />
                                    </Style>
                                </ContextMenu.Resources>
                            </ContextMenu>
                        </StackPanel.ContextMenu>
                    </StackPanel>
                </HierarchicalDataTemplate>
            </TreeView.Resources>
        </TreeView>
    </Grid>
</UserControl>

这由项目的依赖项属性支持。

public ObservableCollection<HierarchyItem> Items
{
    get { return (ObservableCollection<HierarchyItem>)GetValue(ItemsProperty); }
    set { SetValue(ItemsProperty, value); }
}

public static readonly DependencyProperty ItemsProperty = DependencyProperty.Register("Items", typeof(ObservableCollection<HierarchyItem>), typeof(ItemHierarchy), new PropertyMetadata(new ObservableCollection<HierarchyItem>()));

StringToIcon还具有图标名称的字符串依赖项属性作为后盾,由于当前使用的是硬编码图像,因此将其忽略。

对于示例, HierarchyItem很简单:

public ObservableCollection<HierarchyItem> Subitems { get; set; }
public ObservableCollection<BindableMenuItem> MenuItems { get; set; }

为了使该证明有效,我将ItemHierarchy附加到主窗口的某些属性:

public ObservableCollection<BindableMenuItem> MenuItems { get; set; }
public ObservableCollection<HierarchyItem> IHItems { get; set; }
public MainWindow()
{
    MenuItems = new ObservableCollection<BindableMenuItem>();
    MenuItems.Add(new BindableMenuItem("Item", null));
    MenuItems.Add(new BindableMenuItem("Item", null));
    MenuItems.Add(new BindableMenuItem("Item", null));
    MenuItems.Add(new BindableMenuItem("Item", null));

    IHItems = new ObservableCollection<HierarchyItem>();
    IHItems.Add(new HierarchyItem() { MenuItems = this.MenuItems });

    InitializeComponent();
}

编辑2:这也是BindableMenuItem

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

尝试将StringToIcon移动到<TreeView.Resources>

<TreeView ItemsSource="{Binding ElementName=ItemHierarchyControl, Path=Items}">
    <TreeView.Resources>
        <local:StringToIcon x:Key="MenuIcon" x:Shared="False" IconName="{Binding IconName}" />
        <HierarchicalDataTemplate DataType="{x:Type local:HierarchyItem}" ItemsSource="{Binding Subitems}">
            <StackPanel Orientation="Horizontal" Margin="0,1,4,1">
                <TextBlock Text="My text" VerticalAlignment="Center" />
                <StackPanel.ContextMenu>
                    <ContextMenu ItemsSource="{Binding MenuItems}">
                        <ContextMenu.Resources>
                            <Style TargetType="MenuItem">
                                <Setter Property="Header" Value="{Binding Path=Name}" />
                                <Setter Property="Icon" Value="{StaticResource MenuIcon}" />
                            </Style>
                        </ContextMenu.Resources>
                    </ContextMenu>
                </StackPanel.ContextMenu>
            </StackPanel>
        </HierarchicalDataTemplate>
    </TreeView.Resources>
</TreeView>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM