简体   繁体   English

如何使用 WPF 按钮的参数或绑定来更改 XAML styles 中的 fa 图标

[英]How to use parameters or binding for WPF buttons to change fa icons in XAML styles

I made a XAML style for a button in WPF to be used for menu items.我为 WPF 中的按钮制作了 XAML 样式,用于菜单项。 When creating the menu list i want to change the icon (FontAwesome icon) based on a parameter i put into my code to keep it clean and use the same style for the other elements in my button.创建菜单列表时,我想根据我放入代码中的参数更改图标(FontAwesome 图标),以保持其干净,并为按钮中的其他元素使用相同的样式。

However so far I've found that it's not possible to send parameters to styles.但是到目前为止,我发现无法将参数发送到 styles。 So I was wondering how i can achieve it.所以我想知道如何实现它。 I also tried Icon="{Binding Path=Icon}" but i believe this doesn't apply for each button seperately.我也试过 Icon="{Binding Path=Icon}" 但我相信这并不适用于每个按钮单独。

What i have: All icons are the same我所拥有的:所有图标都相同

<Button DockPanel.Dock="Top" x:Name="MenuHome" Style="{StaticResource MenuItem}">Home</Button>

What i want: All icons are different我想要的:所有图标都不一样

<Button DockPanel.Dock="Top" x:Name="MenuHome" Style="{StaticResource MenuItem}" Icon="Home" IconColor="Green">Home</Button>

Code:代码:

    <!-- Menu item button style unclicked -->
    <Style x:Key="MenuItem" TargetType="{x:Type Button}">
        <Setter Property="Height" Value="50"/>
        <Setter Property="Background" Value="#FF33334C"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Button}">
                    <Grid>
                        <Border Background="{TemplateBinding Background}"/>
                        <Grid Name="GridMouseOver" Background="Black" Opacity="0.2" Visibility="Hidden"/>
                        <fa:ImageAwesome Icon="AddressBook" Height="30" Width="30" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="15,0,0,0"/>
                        <TextBlock Text="{TemplateBinding Content}" Foreground="Gainsboro" FontSize="20" TextWrapping="Wrap" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="60,0,0,0"/>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter TargetName="GridMouseOver" Property="Visibility" Value="Visible"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>

            </Setter.Value>
        </Setter>
    </Style>
    
    <!-- Sub menu item button style -->
    <Style x:Key="SubMenuItem" TargetType="{x:Type Button}">
        <Setter Property="Height" Value="50"/>
        <Setter Property="Background" Value="#FF33334C"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Button}">
                    <Grid>
                        <Border Background="{TemplateBinding Background}"/>
                        <Grid Name="GridMouseOver" Background="Black" Opacity="0.2" Visibility="Hidden"/>
                        <fa:ImageAwesome Icon="{Binding Path=Icon}" Height="20" Width="20" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="20,0,0,0"/>
                        <TextBlock Text="{TemplateBinding Content}" Foreground="Gainsboro" FontSize="16" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="60,0,0,0"/>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter TargetName="GridMouseOver" Property="Visibility" Value="Visible"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</Window.Resources>


<!-- Button creation code -->
<Grid>
    <DockPanel>
        <!-- Menu grid -->
        <Grid x:Name="Menu" DockPanel.Dock="Left" Background="#FF33334C">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="200"/>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition  Height="100"/>
                <RowDefinition  Height="1*"/>
            </Grid.RowDefinitions>
            <DockPanel Grid.Row="2" LastChildFill="False">
                <Button DockPanel.Dock="Top" x:Name="MenuHome" Style="{StaticResource MenuItem}">Home</Button>
                <!-- Add visibility Visibility="Collapsed" to the sub menu dock panel-->
                <DockPanel x:Name="SubMenuHome" DockPanel.Dock="Top">
                    <Button DockPanel.Dock="Top" x:Name="SubMenuHome1" Style="{StaticResource SubMenuItem}">Sub Home 1</Button>
                    <Button DockPanel.Dock="Top" x:Name="SubMenuHome2" Style="{StaticResource SubMenuItem}">Sub Home 2</Button>
                </DockPanel>
                <Button DockPanel.Dock="Top" x:Name="MenuProject" Style="{StaticResource MenuItem}">Project</Button>
                <Button DockPanel.Dock="Top" x:Name="MenuTools" Style="{StaticResource MenuItem}">Tools</Button>
            </DockPanel>
        </Grid>
        <Grid x:Name="TitleBar" DockPanel.Dock="Top" Background="#FF33334C">
            <Grid.RowDefinitions>
                <RowDefinition Height="50"/>
            </Grid.RowDefinitions>
        </Grid>
        <Grid x:Name="ChildForm" Background="#FF333346">

        </Grid>
    </DockPanel>

</Grid>

Below is how I improved my code with the help from the answer/info above.以下是我如何在上面的答案/信息的帮助下改进我的代码。

I Implemented FontAwesome 5 instead of the Nuget package FontAwesome.WPF as it holds more icons.我实现了 FontAwesome 5 而不是 Nuget package FontAwesome.WPF 因为它包含更多图标。

  1. Download the resource files from the website从网站下载资源文件

    Download Link FA5 Desktop 下载链接FA5桌面

  2. Create a folder named Fonts in your project (ProjectName.csproj)在您的项目 (ProjectName.csproj) 中创建一个名为 Fonts 的文件夹

    Folder has to be in this level because making multiple folder structures first (Fonts/otf/FA5.otf) didn't work for me.文件夹必须处于此级别,因为首先制作多个文件夹结构(Fonts/otf/FA5.otf)对我不起作用。

  3. Rename it to something easier to type if you like如果您愿意,可以将其重命名为更易于键入的名称

    FaFreeSolid for me FaFreeSolid 对我来说

  4. Copy it into the Fonts folder将其复制到 Fonts 文件夹中

  5. Add it to the project将其添加到项目中

    Project menu -> show all files -> Solution explorer -> Right click the.otf file -> add to project项目菜单 -> 显示所有文件 -> 解决方案资源管理器 -> 右键单击 .otf 文件 -> 添加到项目

  6. Open the.otf font file in Windows and check the name at the top.打开Windows中的.otf字体文件,查看顶部的名称。 Copy it for now暂时复制一下

  7. Create a Resource dictionary创建资源字典

    RMB ProjectName.csproj -> Add -> ResourceDictionary (WPF) -> Named it FontAwesomeResources RMB ProjectName.csproj -> 添加 -> ResourceDictionary (WPF) -> 命名为 FontAwesomeResources

  8. Open the file and create a FontFamily打开文件并创建一个 FontFamily

    Part 1: Key=name to call it with第 1 部分:Key=name 来调用它

    Part 2: Path to the font file第 2 部分:字体文件的路径

    Part 3: #FontName from point 6第 3 部分:第 6 点中的#FontName

Code:代码:

<FontFamily x:Key="FaFreeSolid">/Fonts/FaFreeSolid.otf#Font Awesome 5 Free</FontFamily>
  1. Go to App.xaml to call the resource for the whole project Go 到 App.xaml 调用整个项目的资源

Code:代码:

    <Application.Resources>
            <ResourceDictionary Source="FontAwesomeResources.xaml"/>  
    </Application.Resources>
  1. I used the resource in a textblock for the Text property.我将文本块中的资源用于 Text 属性。 This property then sets the icon image.然后此属性设置图标图像。 The text should be the same as on the website.文字应与网站上的相同。 I noticed that names with a - in its name don't work so you have to use the &#x prefix in the text and use the icon code number behind it.我注意到名称中带有 - 的名称不起作用,因此您必须在文本中使用 &#x 前缀并使用其后面的图标代码编号。 (example: &#xf2b9 = AdressBook) (例如:&#xf2b9 = 地址簿)

    FA Cheat Sheet FA 备忘单

This part makes the "Home" icon show up:这部分使“主页”图标出现:

<TextBlock Text="Home" Foreground="DarkRed" FontFamily="{StaticResource FaFreeSolid}" FontSize="30" VerticalAlignment="Center" Margin="15,0,0,0"/>

MainWindow.xaml:主窗口.xaml:

<!-- Menu item button style unclicked -->
    <Style x:Key="btnMenuItem" TargetType="{x:Type Button}">
        <Setter Property="Height" Value="50"/>
        <Setter Property="Background" Value="Transparent"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Button}">
                    <Border Background="{TemplateBinding Background}">
                        <StackPanel Orientation="Horizontal">
                            <Grid Name="GridMouseOver" Background="Black" Opacity="0.2" Visibility="Hidden"/>
                            <TextBlock Text="Home" Foreground="DarkRed" FontFamily="{StaticResource FaFreeSolid}" FontSize="30" VerticalAlignment="Center" Margin="15,0,0,0"/>
                            <TextBlock Text="{TemplateBinding Content}" Foreground="Gainsboro" FontSize="20" TextWrapping="Wrap" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="20,0,0,0"/>
                        </StackPanel>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter TargetName="GridMouseOver" Property="Visibility" Value="Visible"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

The next problem I have to tackle is creating a dependancy property to set the icon image and icon color through a property when creating a button based on this style.我必须解决的下一个问题是创建一个依赖属性,以便在基于此样式创建按钮时通过属性设置图标图像和图标颜色。

You could try to refer to the following code to bind the Icon to the Tag content of the Button.您可以尝试参考以下代码将 Icon 绑定到 Button 的 Tag 内容。 It contains two methods, you can refer here .它包含两个方法,你可以参考这里

<Style x:Key="FontAwesome">
        <Setter Property="TextElement.FontFamily" Value="pack://application:,,,/Font/#Font Awesome 5 Free Regular" />
    </Style>
    <Style x:Key="MenuItem" TargetType="{x:Type Button}">
        <Setter Property="Height" Value="50"/>
        <Setter Property="Background" Value="#FF33334C"/>
        <Setter Property="TextElement.FontFamily" Value="pack://application:,,,/Font/#Font Awesome 5 Free Regular" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Button}">
                    <Grid>
                        <Border Background="{TemplateBinding Background}"/>
                        <Grid Name="GridMouseOver" Background="Black" Opacity="0.2" Visibility="Hidden"/>
                        <fa:ImageAwesome Icon="{Binding Tag, RelativeSource={RelativeSource FindAncestor,  AncestorType=Button} }" Height="30" Width="30" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="15,0,0,0"/>
                        <TextBlock Text="{TemplateBinding Content}" Foreground="Gainsboro" FontSize="20" TextWrapping="Wrap" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="60,0,0,0"/>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter TargetName="GridMouseOver" Property="Visibility" Value="Visible"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>

            </Setter.Value>
        </Setter>
    </Style>
    <Style x:Key="MenuItem2" TargetType="{x:Type Button}">
        <Setter Property="Height" Value="50"/>
        <Setter Property="Background" Value="#FF33334C"/>
        <Setter Property="TextElement.FontFamily" Value="pack://application:,,,/Font/#Font Awesome 5 Free Regular" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Button}">
                    <Grid>
                        <Border Background="{TemplateBinding Background}"/>
                        <Grid Name="GridMouseOver" Background="Black" Opacity="0.2" Visibility="Hidden"/>
                        <TextBlock Text="{Binding Tag, RelativeSource={RelativeSource FindAncestor,  AncestorType=Button} }" FontSize="22" Margin="14" HorizontalAlignment="Left" VerticalAlignment="Center" Style="{DynamicResource  FontAwesome}" />
                        <TextBlock Text="{TemplateBinding Content}" Foreground="Gainsboro" FontSize="20" TextWrapping="Wrap" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="60,0,0,0"/>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter TargetName="GridMouseOver" Property="Visibility" Value="Visible"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>

            </Setter.Value>
        </Setter>
    </Style>

<Grid x:Name="Menu" DockPanel.Dock="Left" Background="#FF33334C">
               ...
               <DockPanel Grid.Row="2" LastChildFill="False">
                <Button DockPanel.Dock="Top" x:Name="MenuHome" Style="{StaticResource MenuItem}" Tag="home">Home</Button>
                <DockPanel x:Name="SubMenuHome" DockPanel.Dock="Top" >
                    <Button DockPanel.Dock="Top" x:Name="SubMenuHome1" Style="{StaticResource SubMenuItem}">Sub Home 1</Button>
                    <Button DockPanel.Dock="Top" x:Name="SubMenuHome2" Style="{StaticResource SubMenuItem}">Sub Home 2</Button>
                </DockPanel>
                <Button DockPanel.Dock="Top" x:Name="MenuProject" Style="{StaticResource MenuItem2}"  Tag="&#xf542;">Project
                </Button>
            </DockPanel>
            </Grid>

The result:结果:

在此处输入图像描述

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

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