【问题标题】:Dynamic PAth Icon Buttons in a Collection ItemTemplate Resource w/ MouseOver带有 MouseOver 的集合 ItemTemplate 资源中的动态路径图标按钮
【发布时间】:2016-06-17 07:29:13
【问题描述】:

我正在处理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,它有自己的控制模板....您的背景来自amigo。 ;) ...您可以使这件事更有条理,并使用一小部分 xaml 和 DOM 对象提供相同的功能。
  • 这是因为他们将其作为MenuItem 放入其中,通过高亮画笔为其背景边框赋予颜色#ddd 颜色。
  • 是的,现在我所在的时区已经下班了,我有差事要跑,但明天我会告诉你一些事情。基本上,您的 ItemTemplate 将成为使用 ONE 样式的 ONE 按钮,您不必更改任何绑定,并且可以丢弃转换器和其余的垃圾,将仅是 xaml,您将完成。好吧,我认为至少,你是如何保存你的“ImageAddress”的?它只是一个带有路径数据的字符串吗?

标签: wpf xaml visual-studio-2015 app.xaml


【解决方案1】:

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

但是,如果情况并非如此,并且您实际上使用的图像也很好,只需将按钮模板中的 Path 对象替换为 Image 或任何您想做的事情。所以无论如何,这就是我用一个简单的例子做的事情,从你在 Resource dict 或任何地方的资源开始;

<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 设置默认值; &lt;Setter Property="Tag" Value="{StaticResource DefaultIconResourceName}"/&gt; 就是这样,如果有人忘记设置一个,你就有一个。

现在我们有了按钮设置,但是如何在通过集合创建它们的实例中使用它?好吧,我们只需将您当前的 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 等,您可以在表单中添加您需要的任何内容。

【讨论】:

  • @tCoe 呃,不是真的,花了大约十分钟。如果它回答了您的问题,您可能会点击那里的复选标记图标以将其标记为正确,这样人们就知道您已排序。祝朋友周末愉快!
  • 是的,DataPath 元素的属性,该元素包含您的路径几何。
  • @tCoe 是的,如果您在 Button 模板内的 Path 上看到 Fill 属性,我将其设置为示例中的十六进制颜色。你可以在那里改变它。如果需要,您还可以添加一个触发器以在悬停时更改它,或者您可以 TemplateBinding 到 Foreground,它将继承任何 Foreground 颜色。或者,如果您想获得真正的幻想,可以添加 attached property 以将其设置为内联按钮的实例。
  • @tCoe 请参阅答案底部的附录以获取更多信息以处理他们的悬停颜色差异,并祝周末愉快!
  • @tCoe 确定,请参阅更新答案底部的“附录的附录”。此外,我经常做的一件事就是将另一个边框放在所有内容的顶部,并使用禁用的画笔作为背景等,并为 IsEnabled=false 单独切换它的可见性,而不是将 setter 应用于每个实例的同一对象的不同属性。因此,如果它被禁用,整个按钮只会为禁用的视觉效果获得一个半透明的覆盖。 :)
猜你喜欢
  • 2013-07-05
  • 2013-03-19
  • 1970-01-01
  • 2023-03-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多