Динамические кнопки значков PAth в коллекции ItemTemplate Resource w/ MouseOver

Я работаю с иконками.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);
    }
  }
}

1 ответ

Решение

Итак, после того, как вы обновили свой вопрос, и мы выяснили, что вашим виновником было использование MenuItem и это унаследованный шаблон управления, дающий серый цвет #ddd в выделении, о котором мы говорили о быстром рефакторинге для лучших практик. Итак, вот пример того, о чем я говорил (что вы, вероятно, захотите немного настроить в соответствии со своими потребностями) и предполагает, что ваш "ImageAddress" просто указывает на данные пути Geometry для создания ваших значков.

Однако, если это не так, и вы буквально используете изображения, это тоже хорошо, просто поменяйте местами 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>

Это позволяет быстро, легко и удобно хранить значки, использовать их по мере необходимости и т. Д. Я бы рекомендовал установить значение по умолчанию для 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 и наш передний план отражает это состояние, используя кисти Disabled по умолчанию, находясь в этом состоянии.

Имейте в виду, что это все еще Button управление и поставляется со всеми встроенными функциями любой стандартной кнопки по умолчанию. Мы просто не охватили все основы ради этого примера.

Поэтому, если вам нужны IsEnabled, IsKeyboardFocused, IsPressed и т. Д., Вы можете просто добавить в форму все, что вам нужно.

Другие вопросы по тегам