带有 MouseOver 的集合 ItemTemplate 资源中的动态路径图标按钮

Dynamic PAth Icon Buttons in a Collection ItemTemplate Resource w/ MouseOver

我正在处理 icons.XAML 图像,将它们插入到文本块上方的按钮中。一切看起来都很棒,直到我将鼠标悬停在图像本身上。仅图片上方出现灰色框:

如何摆脱灰框?

这是其中一个图标:

<Canvas x:Key="appbar_cog" Width="38" Height="46" Clip="F1 M 0,0L 76,0L 76,76L 0,76L 0,0" Background="Transparent">
    <Path Width="37.6263" Height="37.6262" Canvas.Left="15" Canvas.Top="5" Stretch="Fill" Fill="#FF5DBEBE" Data="F1 M 27.5314,21.8628L 33.0126,19.4224L 34.7616,23.3507C 36.6693,22.9269 38.6044,22.8903 40.4668,23.2026L 42.0083,19.1868L 47.6098,21.337L 46.0683,25.3528C 47.6612,26.3669 49.0747,27.6889 50.2088,29.2803L 54.1371,27.5313L 56.5776,33.0126L 52.6493,34.7616C 53.0731,36.6693 53.1097,38.6043 52.7974,40.4668L 56.8131,42.0083L 54.6629,47.6097L 50.6472,46.0683C 49.6331,47.6613 48.3111,49.0748 46.7197,50.2089L 48.4686,54.1372L 42.9874,56.5776L 41.2384,52.6493C 39.3307,53.0731 37.3957,53.1097 35.5333,52.7974L 33.9918,56.8131L 28.3903,54.6629L 29.9318,50.6472C 28.3388,49.6331 26.9252,48.3111 25.7911,46.7196L 21.8628,48.4686L 19.4224,42.9873L 23.3507,41.2383C 22.9269,39.3307 22.8903,37.3957 23.2026,35.5332L 19.1869,33.9918L 21.3371,28.3903L 25.3528,29.9318C 26.3669,28.3388 27.6889,26.9252 29.2804,25.7911L 27.5314,21.8628 Z M 34.3394,29.7781C 29.7985,31.7998 27.7564,37.1198 29.7781,41.6606C 31.7998,46.2015 37.1198,48.2436 41.6606,46.2219C 46.2015,44.2002 48.2436,38.8802 46.2219,34.3394C 44.2002,29.7985 38.8802,27.7564 34.3394,29.7781 Z "/>
</Canvas>

这是我正在使用的按钮:

<Style x:Key="MenuButtonStyle" TargetType="{x:Type Button}">
            <Setter Property="Background" Value="#FF496161"/>
            <Setter Property="OverridesDefaultStyle" Value="True"/>
            <Setter Property="Margin" Value="0"/>
            <Setter Property="Template">
                <Setter.Value>

                    <ControlTemplate TargetType="{x:Type Button}">
                        <Border Name="Border" 
                        BorderThickness="3"
                        Padding="4,2" 
                        BorderBrush="#ff496161" 
                        CornerRadius="3" 
                        Background="{TemplateBinding Background}">
                            <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
                        </Border>

                        <ControlTemplate.Triggers>
                                <Trigger Property="IsMouseOver" Value="True">
                                <Setter TargetName="Border" Property="Background" Value="White"/>
                                <Setter TargetName="Border" Property="BorderBrush" Value="DarkOrange" />
                                </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

这是我调用图像的 MenuView:

  </UserControl.Resources>
<ItemsControl ItemsSource="{Binding Path=MenuItems}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Button x:Name="MenuButton" Width="110"  VerticalContentAlignment="Top" HorizontalContentAlignment="Center" Margin="0 0 0 0" IsEnabled="{Binding Path=IsActive}"
                    Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}, Path=DataContext.MenuSelectedCommand}" 
                    CommandParameter="{Binding Path=CommandName}" Style="{StaticResource MenuButtonStyle}">
                <StackPanel x:Name="MenuPanel" Orientation="Vertical">
                    <MenuItem x:Name="Picture" HorizontalAlignment="Center" Icon="{Binding ImageAddress, Converter={StaticResource StringToResourceConverter}}" Background="Transparent"/>
                    <TextBlock x:Name="Words" HorizontalAlignment="Stretch" Margin="0 0 0 0" TextAlignment="Center" Text="{Binding Description}" FontFamily="Arial" FontSize="14" />                           
                </StackPanel>

            </Button>
            <DataTemplate.Triggers>

                <Trigger SourceName="MenuButton" Property="IsMouseOver" Value="True">
                    <Setter TargetName="Words" Property="Foreground" Value="Black"/>

                 </Trigger>

                <Trigger SourceName="MenuButton" Property="IsMouseOver" Value="False">
                    <Setter TargetName="Words" Property="Foreground" Value="White"/>

                </Trigger>

            </DataTemplate.Triggers>
        </DataTemplate>

    </ItemsControl.ItemTemplate>
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Orientation="Horizontal" HorizontalAlignment="Stretch" Margin="0 0 0 0" Background="#496161">
            </StackPanel>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>

</ItemsControl>

编辑:这是订购我的图标的 MenuItems 脚本。

namespace Inspection.Desktop.Common.ViewModel
{
public class MenuViewModel : BaseViewModel
{

    public ObservableCollection<MenuItem> MenuItems { get; set; }

    public MenuViewModel()
    {

    }

    public override void InitiatedData()
    {
        MenuItems = new ObservableCollection<MenuItem>();

        MenuItems.Add(new MenuItem { CommandName = "WorkList", Description = "My WorkList", ImageAddress = "appbar_home", RoleName = "Electrical", WirelessRequired = true });
        MenuItems.Add(new MenuItem { CommandName = "Download", Description = "Download", ImageAddress = "appbar_cloud_download", RoleName = "Electrical", WirelessRequired = true });
        MenuItems.Add(new MenuItem { CommandName = "FieldRequest", Description = "Field Request", ImageAddress = "appbar_input_pen", RoleName = "FAS", WirelessRequired = false });
        MenuItems.Add(new MenuItem { CommandName = "Mileage", Description = "Mileage", ImageAddress = "appbar_transit_car", RoleName = "FAS", WirelessRequired = false });
        MenuItems.Add(new MenuItem { CommandName = "Calendar", Description = "Calendar", ImageAddress = "appbar_calendar", RoleName = "FAS", WirelessRequired = true });
        MenuItems.Add(new MenuItem { CommandName = "Assign", Description = "Assign", ImageAddress = "appbar_list_check", RoleName = "Electrical", WirelessRequired = true });
        MenuItems.Add(new MenuItem { CommandName = "Reports", Description = "Reports", ImageAddress = "appbar_graph_line_up", RoleName = "Electrical", WirelessRequired = true });
        MenuItems.Add(new MenuItem { CommandName = "PAIRS", Description = "Go To PAIRS", ImageAddress = "appbar_globe", RoleName = "Electrical", WirelessRequired = true });
        MenuItems.Add(new MenuItem { CommandName = "Settings", Description = "Settings", ImageAddress = "appbar_cog", RoleName = "Electrical", WirelessRequired = false });

    }

    public override void InitiatedCommand()
    {
        MenuSelectedCommand = new RelayCommand<string>(MenuClicked);
    }

    public override void InitiatedMessages() { }

    public RelayCommand<string> MenuSelectedCommand { get; private set; }

    public void MenuClicked(string name)
    {
        //MenuItems.ToList().ForEach((menu)=> {
        //                                    menu.IsActive = menu.CommandName.ToLower() == name.ToLower() ? false : true;
        //                                    });
        Utilities.Messenger.InspectionMessenger.SendMessage<string>(Messages.VIEW_CHANGED, name);
    }
  }
}

好的,所以在您更新问题后,我们发现您的罪魁祸首是 MenuItem 的使用,它是继承的控件模板,在突出显示时给出 #ddd 灰色,我们讨论了一些快速重构以更好做法。所以这是我所说的一个例子(你可能想稍微调整一下以满足你的需要)并假设你的 "ImageAddress" 只是指向几何路径数据来创建你的图标。

但是,如果情况并非如此,并且您实际上使用的图像也很好,只需将按钮模板中的 Path 对象替换为 Image 或您想要执行的任何操作。所以无论如何,这就是我用一个快速示例所做的事情,从您在资源字典或任何地方放置的资源开始;

<Window.Resources>
        <!-- The "icons" -->
        <Geometry x:Key="ExampleIcon">M78,63 L69.333333,75 54.00093,76.333333 67.333747,89.000655 64.667184,101.66764 78.666641,93.667175 89.332417,102.33399 90.66603,89.667334 103.33171,77.00035 86.666127,75.666984 z</Geometry>
        <Geometry x:Key="ExampleIcon2">M72,62 L48,83 69,106 92,87 z</Geometry>

        <!-- The Button Template -->
        <Style x:Key="NeatoButtonStyle" TargetType="{x:Type Button}">
            <Setter Property="OverridesDefaultStyle" Value="True"/>
            <Setter Property="Background" Value="Transparent"/>
            <Setter Property="BorderBrush" Value="Transparent"/>
            <Setter Property="Foreground" Value="White"/>
            <Setter Property="BorderThickness" Value="3"/>
            <Setter Property="HorizontalContentAlignment" Value="Center"/>
            <Setter Property="VerticalContentAlignment" Value="Center"/>
            <Setter Property="Padding" Value="4,2"/>
            <Setter Property="Cursor" Value="Hand"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Button}">                      

                            <Grid>
                                <Grid.RowDefinitions>
                                    <RowDefinition/>
                                    <RowDefinition Height="Auto"/>
                                </Grid.RowDefinitions>

                                <Border Grid.RowSpan="2"
                                        x:Name="border" 
                                        BorderBrush="{TemplateBinding BorderBrush}" 
                                        BorderThickness="{TemplateBinding BorderThickness}" 
                                        Background="{TemplateBinding Background}" 
                                        SnapsToDevicePixels="true"/>

                                <Path Stretch="Uniform"
                                      Data="{TemplateBinding Tag}"
                                      Fill="#FF5DBEBE"
                                      Margin="{TemplateBinding Padding}"/>

                                <ContentPresenter Grid.Row="1"
                                                  x:Name="contentPresenter" 
                                                  Focusable="False"                                               
                                                  Margin="{TemplateBinding Padding}" 
                                                  RecognizesAccessKey="True" 
                                                  SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                                                  HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                                  VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>

                            </Grid>

                        <ControlTemplate.Triggers>

                            <Trigger Property="IsMouseOver" Value="true">
                                <Setter Property="Background" TargetName="border" 
                                        Value="White"/>
                                <Setter Property="BorderBrush" TargetName="border" 
                                        Value="DarkOrange"/>
                                <Setter Property="TextElement.Foreground" TargetName="contentPresenter" 
                                        Value="Black"/>
                            </Trigger>

                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

    </Window.Resources>

所以你会注意到我把你分离出来的所有东西都放在一个模板中,你可以从任何地方使用。顶部还有几个示例(尽管是快速的小绘图 lol)图标示例路径数据。所以说我们现在需要制作按钮。那么你只需通过方便的花花公子 Tag 属性 在实例中调用你想要的图标;

<StackPanel Orientation="Horizontal" 
    HorizontalAlignment="Center" VerticalAlignment="Center">

        <Button Content="Blah Blah"
                Style="{StaticResource NeatoButtonStyle}"
                Tag="{StaticResource ExampleIcon}"/>

        <Button Content="Blah Blah"
                Style="{StaticResource NeatoButtonStyle}"
                Tag="{StaticResource ExampleIcon2}"/>

</StackPanel>

这允许一种快速、简单且易于管理的方式来存储您的图标,根据需要使用它们等。我建议通过 setter 在模板中为 Tag 设置默认值; <Setter Property="Tag" Value="{StaticResource DefaultIconResourceName}"/> 就这样,如果有人忘记设置一个,你那里有一个。

现在我们已经设置了按钮,但是如何在通过集合创建它们的实例中使用它呢?好吧,我们只是将您当前的 ItemTemplate 换成类似的东西;

<ItemsControl.ItemTemplate>
   <DataTemplate>

      <Button Content="{Binding Description}"                 
              Tag="{Binding ImageAddress}"
              Style="{StaticResource NeatoButtonStyle}"/>

   </DataTemplate>
</ItemsControl.ItemTemplate>

这样做消除了一堆不必要的混乱,并删除了所有那些使用其他嵌套模板控件为每个实例创建的不必要的 DOM 元素。

就是这样,你已经完成了。现在,如果说你到处都使用按钮并且有人决定需要调整某些东西,你就在一个地方做,它会被继承到每个实例。以及为您可能需要轻松更改其他内容的一次性场景提供更多灵活性。

无论如何希望这对您有所帮助。干杯!

附录

如果您想在路径中添加诸如 "Hover State" 之类的内容,您只需在按钮模板内向 Path 添加一个名称,例如;

<Path x:Name="ButtonIcon"
      Stretch="Uniform"
      Data="{TemplateBinding Tag}"
      Fill="#FF5DBEBE"
      Margin="{TemplateBinding Padding}"/>

然后只需将它的触发器添加到现有的 IsMouseOver 已经位于按钮模板中的触发器,例如;

<Setter Property="Fill" 
        TargetName="ButtonIcon" 
        Value="Red"/>

附录的附录:

因此,要添加禁用状态,我们只需添加另一个触发器来为我们处理它,并给出禁用的视觉效果。所以我们会在我们已经处理 IsMouseOver 的模板中添加另一个这样的触发器。

<Trigger Property="IsEnabled" Value="false">
   <Setter TargetName="border" 
           Property="Background" 
           Value="{StaticResource DisabledBackgroundBrush}" />
   <Setter TargetName="border" 
           Property="BorderBrush" 
           Value="{StaticResource DisabledBorderBrush}" />
   <Setter Property="Foreground" 
           Value="{StaticResource DisabledForegroundBrush}"/>
</Trigger>

所以现在当 IsEnabled=False 时,我们的 Border 和我们的前景通过在该状态下使用默认禁用画笔来反映该状态。

请记住,它仍然是一个 Button 控件,并且具有任何标准默认按钮的所有内置功能。为了这个例子,我们只是没有涵盖所有的基础。

因此,如果您需要 IsEnabled、IsKeyboardFocused、IsPressed 等,您可以在其中添加所需的任何内容。