在 Collection ItemTemplate 资源中使用动态路径图标按钮,带有鼠标悬停效果。

6
我正在使用icons.XAML图像,并将它们插入到文本块上方的按钮中。一切看起来都很好,直到我悬停在图像上时。一个灰色框仅出现在图片上:

enter image description here

如何去掉这个灰色框?

这是其中一个图标:

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

1
@ChrisW。我会尝试获取应用程序出现问题的屏幕截图,以便您可以看到我在说什么。您创建资源的方法正是我想要做的,但我找不到它来自哪里。也许图片会有所帮助。 - tCoe
2
你的应用程序中有关于canvas的样式吗? - XAMlMAX
2
哦...你将你的“图片”嵌入到了一个具有自己控件模板的MenuItem中...这就是你背景来自的地方,伙计。 ;) ...你可以更好地组织它,并使用少量的XAML和DOM对象实现相同的功能。 - Chris W.
3
这是因为它们将其作为MenuItem嵌入其中,这通过高亮时使用的刷子将其背景边框设置为颜色#ddd。 - Chris W.
2
是的,在我的时区,现在是下班时间了,我还有一些事情要处理,但明天我会给你弄出来。基本上,你的ItemTemplate将变成一个按钮,使用一个样式,你不需要更改任何绑定,并且可以放弃转换器和其他垃圾,只需使用XAML即可完成。好吧,至少我认为是这样,你是如何保存“ImageAddress”的?它只是一个带有路径数据的字符串吗? - Chris W.
显示剩余13条评论
1个回答

3

好的,当您更新了问题并且我们发现您的问题是使用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>

你会注意到我把你分开的所有内容都放在了一个模板中,你可以从任何地方使用它。在顶部还有一些示例(尽管是草率的快速绘图)图标示例路径数据。所以现在假设我们需要制作按钮。那么你只需要在实例的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元素来删除它们。

就是这样,完成了。现在,如果你在各个地方使用按钮,有人决定需要调整一些东西,你只需要在一个地方进行修改,就可以继承到每个实例中。同时,也允许在一些单独的场景中更灵活地改变其他内容。

无论如何,希望这能帮到你。干杯!

补充说明

如果你想为路径添加类似于“悬停状态”的内容,你只需要在按钮模板中为你的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等等,您可以根据需要添加。


1
是的,Data 是持有你的路径几何图形的 Path 元素的属性。 - Chris W.
1
@tCoe,请查看答案底部的附录以获取更多信息,以处理他们的悬停颜色差异,并祝你周末愉快! - Chris W.
1
@tCoe 当然,可以看一下更新答案底部的“附录”。此外,我经常做的一件事情就是在所有内容上方再加一个边框,使用禁用画刷作为背景等,并单独为IsEnabled=false切换其可见性,而不是为每个实例应用不同属性的设置器。因此,如果它被禁用,整个按钮就会得到一个半透明的覆盖层,以显示禁用状态。 :) - Chris W.
1
@tCoe 当然,兄弟。所以,你只需在 Button 所在的 ItemTemplate 中添加类似 IsEnabled="{Binding DataContext.IsEnabled, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type MyControl}}}" 的内容,然后就可以从父 ViewModel 中访问 IsEnabled 或者从列表 ViewModel 中调用 IsEnabled="{Binding Blah}" 了。明白了吗?如果是动态的,别忘了通知属性更改。 - Chris W.
1
@tCoe 是的,“MyControl”只是父级数据上下文的任何内容。因此可以是窗口、用户控件或其他任何东西。您始终可以为视图命名一个x:Name,并将祖先内容替换为ElementName=TheViewsOrControlsxName,重点是您只是尝试从ItemTemplate的数据模板内部访问数据上下文。 - Chris W.
显示剩余19条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接