WPF自定义按钮最佳方法

2024-02-27

我想创建一个自定义Button在 WPF 内部。当然,该按钮将是一个用户控件,它将包含许多视觉元素(如描边、高光、阴影、发光、图像等)。

问题是,如果我使用 DependencyProperties 并将它们绑定在 XAML 中,我将无法在 DesignTime 看到结果(我尝试实现 IsInDesignMode 方法,但由于某种原因,我无法理解我的 VS 在我在 UserControls 上使用这个方法,否则它工作得很好),这绝对不好。

所以我正在考虑根本不使用 XAML 并在后面的代码中完成所有工作。

你们有什么感想?


和您一样,当我开始并想了解正在发生的情况以及如何使用模板时,需要进行大量的试验和错误。希望我的研究和一些分步组件可以帮助您根据自己的喜好进行定制并了解事物的来源。

首先,当尝试了解新的“模板样式”如何工作时,我为我的任何操作样式创建了一个简单的独立 WPF 应用程序(“AMS”)。这样,我不必永远等待,看看在我的主要项目和主题的其余部分的尝试/错误期间会是什么样子。

由此,我创建了一个名为“TestingStyles”的新 WPF 窗口。保存/编译,运行,没问题。

现在,在“TestingStyles”窗口的“查看代码”中,我已将我正在使用的任何内容放入自定义类中......为了帮助逐步显示,我创建了以下内容:

namespace AMS
{
    /// <summary>
    /// Interaction logic for TestingStyles.xaml
    /// </summary>
    public partial class TestingStyles : Window
    {
        public TestingStyles()
        {
            InitializeComponent();
        }
    }

    // Enumerator for a custom property sample...
    public enum HowToShowStatus
    {
        ShowNothing,
        ShowImage1
    }


    public class YourCustomButtonClass : Button
    {
        public YourCustomButtonClass()
        {
            // auto-register any "click" will call our own custom "click" handler
            // which will change the status...  This could also be done to simplify
            // by only changing visibility, but shows how you could apply via other
            // custom properties too.
            Click += MyCustomClick;
        }

        protected void MyCustomClick(object sender, RoutedEventArgs e)
        {
            if( this.ShowStatus == HowToShowStatus.ShowImage1 )
                this.ShowStatus = HowToShowStatus.ShowNothing;
            else
                this.ShowStatus = HowToShowStatus.ShowImage1;
        }


        public static readonly DependencyProperty ShowStatusProperty =
              DependencyProperty.Register("ShowStatus", typeof(HowToShowStatus),
              typeof(YourCustomButtonClass), new UIPropertyMetadata(HowToShowStatus.ShowNothing));

        public HowToShowStatus ShowStatus
        {
            get { return (HowToShowStatus)GetValue(ShowStatusProperty); }
            set { SetValue(ShowStatusProperty, value); }
        }
    }

}

正如您所看到的,自定义“Button”类,我在默认的TestingStyles:Window声明之外的底部......所以它都在同一个“Project”中。

在此 XAML 示例中,我引用了“TaskComplete.png”图形文件(该文件应该仅用于示例目的,直接添加到项目中......即使是用于示例目的的简单笑脸)。 因此,创建一个如此简单的 .png 文件...即使使用 Microsoft Paint 并画一个带有眼睛和微笑的圆圈。保存到项目的根目录中(稍后再讨论路径,先让它工作)。

保存并重新编译项目,以便当您开始定义 XAML 模板时,项目公开知道新“类”(按钮)是什么。

现在,回到 TestStyles 设计器并将其置于分屏中,以便您可以看到设计器和 XAML 标记...只需替换为以下内容...

<Window x:Class="AMS.TestingStyles"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:my="clr-namespace:AMS"
        Title="TestingStyles" Height="300" Width="300" >

    <Window.Resources>
        <!-- Build a "Style" based on an anticpated target control type of YourCustomButtonClass.
            per the "my:" reference, the "my" is an "alias" to the xmlsn:my in the declaration above,
            so the XAML knows which library to find such control.  In this case, I've included within
            the actual forms's 'View Code' as a class at the bottom.  

            As soon as you assign an "x:Key" reference, its like its telling XAML to make this a PRIVATE
            style so you don't reference it explicitly (yet)
        -->
        <Style TargetType="my:YourCustomButtonClass" x:Key="keyYourCustomButtonClass">
            <!-- put whatever normal "settings" you want for your common look / feel, color -->
            <Setter Property="BorderThickness" Value="1"/>
            <Setter Property="HorizontalContentAlignment" Value="Center"/>
            <Setter Property="VerticalContentAlignment" Value="Center"/>
            <Setter Property="Padding" Value="0,0,1,1"/>
            <Setter Property="Width" Value="100" />
            <Setter Property="Height" Value="30" />

            <!-- Now, for the template of the button.  Things can get really crazy here
              as you are now defining what you want the "button" to look like, borders, 
              content, etc. In this case, I have two borders to give the raise/sunken effect 
              of a button and it has its own colors -->
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="Button" >
                        <!-- The x:Name references used during triggers to know what it is "applying" changes to -->
                        <Border x:Name="BorderTopLeft"
                                BorderBrush="Gainsboro" 
                                BorderThickness="0,0,1.5,1.5">

                            <Border x:Name="BorderBottomRight"
                                BorderBrush="Gray" 
                                BorderThickness="1.5,1.5,0,0">
                                <!-- Now, what control  type do you want the button to have... 
                                    Ex: You could use a grid (as I have here), stack panels, etc -->
                                <Grid Background="LightBlue" >
                                    <!-- I'm defining as two columns wide, one row tall.  
                                        First column fixed width 20 pixels example for an image -->
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="20px" />
                                        <ColumnDefinition Width="*" />
                                    </Grid.ColumnDefinitions>
                                    <Grid.RowDefinitions>
                                        <RowDefinition />
                                    </Grid.RowDefinitions>

                                    <!-- Now, create the controls I want available within my "template".
                                        when assigned with "x:Name", thats like a property withing the template
                                        that triggers can associate and update to. -->
                                    <Image x:Name="btnImage" 
                                        Grid.Row="0" Grid.Column="0"
                                        Stretch="None"
                                        VerticalAlignment="Stretch" HorizontalAlignment="Stretch" 
                                        Source="TaskComplete.png"
                                        Visibility="Visible" />

                                    <!-- and also have the text for the button to show the user -->
                                    <TextBlock x:Name="txtNewBtn" 
                                        Grid.Row="0" Grid.Column="1"
                                        Padding="5"
                                        HorizontalAlignment="Left"
                                        VerticalAlignment="Center"
                                    Text="{TemplateBinding Content}" />
                                    <!-- The "{TemplateBinding Content}" means to set the text based on 
                                        the "CONTENT" property of the original button and not use a fixed value -->
                                </Grid>
                            </Border>
                        </Border>
                        <!-- Now, some triggers for the button itself... some can be property based, others data-based -->
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsPressed" Value="true">
                                <!-- What properties do we want to change when user CLICKS
                                    on the button, give the "EFFECT" of click down/up by
                                    changing the "Margin" and border thicknesses...  -->
                                <Setter Property="Margin" Value="1,1,0,0"/>
                                <!-- Notice the "TargetName" below referring to the x:Name I've applied in template above 
                                    so when the user clicks on the button, it changes the border thickness properties of
                                    each to give the effect of a normal button clicking.  I'm widening one border, shrinking other -->
                                <Setter TargetName="BorderTopLeft" Property="BorderThickness" Value="2.5,2.5,0,0"/>
                                <Setter TargetName="BorderBottomRight" Property="BorderThickness" Value="0,0,.5,.5"/>
                            </Trigger>

                            <!-- Here, I have a custome property on the class for "ShowStatus".  The binding is to itself
                                regardless of how many instances of this type of "button" are on a given form 
                                First trigger happens when the value is changed to "ShowNothing", but can also change 
                                when set to "ShowImage1" or other as you may need applicable
                            -->
                            <DataTrigger Binding="{Binding Path=ShowStatus, RelativeSource={RelativeSource Self}}" Value="ShowNothing">
                                <Setter TargetName="btnImage" Property="Visibility" Value="Hidden"/>
                            </DataTrigger>
                            <DataTrigger Binding="{Binding Path=ShowStatus, RelativeSource={RelativeSource Self}}" Value="ShowImage1">
                                <Setter TargetName="btnImage" Property="Visibility" Value="Visible"/>
                            </DataTrigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

        <!-- NOW, we can expose any instance of "YourCustomButtonClass" button to use the style based on definition above 
            any instance of such YourCustomButtonClass will automatically reflect this style / look -->
        <Style TargetType="my:YourCustomButtonClass" BasedOn="{StaticResource keyYourCustomButtonClass}" />

    </Window.Resources>

    <Grid>
        <my:YourCustomButtonClass Content="Button" VerticalAlignment="Top" ShowStatus="ShowImage1" />
    </Grid>
</Window>

这将为您提供一个很好的起点来定义您自己的模板以及元素如何开始结合在一起。该示例运行后,当您更改模板的任何颜色、边距、填充等时,您将立即看到该组件对控件的视觉影响。

玩得开心,不要把头撞到墙上太多......

顺便说一句,一旦这工作正常,那么您就可以在

<Window.Resources>
</Window.Resources> 

并将其放入 Windows 资源字典中,使其成为项目的全局变量,而不仅仅是此测试表单。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

WPF自定义按钮最佳方法 的相关文章

  • 如何禁用列表框上的突出显示但保留选择?

    我无法找到如何不允许我的列表框突出显示所选项目 我知道我没有添加触发器来突出显示该项目
  • 有没有基于 WPF 的 Markdown 渲染器? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我们有基于 WPF 的应用程序 我们有单独的字符串存储库 其中的文本在网络中进行编辑 在我们的 WPF
  • 获取 TreeView 中子节点的 SelectedIndex

    我目前正在使用 C 开发一个 wpf 项目 我创建了一个树视图 其中包含父节点和子节点 我想知道是否有办法获取用户单击的子节点的索引 类似于使用组合框时的 SelectedIndex 我尝试过各种方法 例如 int val TreeView
  • Discord.py 嵌入中禁用按钮/冻结按钮

    I m trying to make a replica of this bot in which when I press any of the buttons below it shows a dropdown menu and you
  • 将 MahApps 图标与 ContextMenu 结合使用

    我正在使用 MahApps Metro UI 工具包编写 WPF 应用程序 http mahapps com guides quick start html http mahapps com guides quick start html
  • Javafx 从 TextField 获取输入

    这是我当前的代码 它所做的只是为我制作的计算器设置一个 GUI 界面 我希望用户输入两个值 然后当按下 Sum 按钮时 它将两个值加在一起并将其显示在 Sum 文本字段中 我正在尝试使用 JavaFX 如果您能提供一些帮助 我将不胜感激 i
  • 如何在函数执行后停止 tkinter?

    我在停止 提要 时遇到问题 cancel 参数似乎对 after 方法没有任何影响 尽管 feed stop 被打印到控制台 我正在尝试使用一个按钮来启动源 另一个按钮来停止源 from Tkinter import Tk Button i
  • 通过等待任务或访问其 Exception 属性都没有观察到任务的异常

    这些是我的任务 我应该如何修改它们以防止出现此错误 我检查了其他类似的线程 但我正在使用等待并继续 那么这个错误是怎么发生的呢 通过等待任务或访问其 Exception 属性都没有观察到任务的异常 结果 未观察到的异常被终结器线程重新抛出
  • 需要使用手机后退按钮返回 Web 视图的帮助

    这是我的代码 package com testappmobile import android app Activity import android os Bundle import android view KeyEvent impor
  • 如何在 wpf 应用程序的代码隐藏中创建集合视图源

    我有以下代码 public partial class MainWindow Window public MainWindow InitializeComponent var entities new DemoEntities var de
  • 当按钮处于加载状态时,如何向按钮添加微调器图标?

    Twitter 引导按钮 http getbootstrap com javascript buttons有一个很好的Loading 状态可用 问题是它只显示一条消息 例如Loading 通过了data loading text像这样的属性
  • 从固定文档中删除页面?

    如何从固定文档中删除页面 我添加这样的页面 Add page to pageContent PageContent pageContent new PageContent IAddChild pageContent AddChild fix
  • Kivy - 单击按钮时编辑标签

    我希望 Button1 在单击时编辑标签 etykietka 但我不知道如何操作 你有什么想法吗 class Zastepstwa App def build self lista WebOps getList layout BoxLayo
  • 绑定导致 StackOverflow

    我不确定我在这里做错了什么 可以说 我有两个用户控件BoxAand BoxB 两者都有一个名为的 DependencyPropertyText BoxB 包装了具有常规 TextBox 的 BoxA 绑定应该像这样 BoxB Text Bo
  • 异步WCF调用来保存线程?

    In 另一个问题 https stackoverflow com q 19731600 279516 建议我发送异步网络请求 而不是在后台线程上发送同步请求 原因是为了不浪费一根线 我试图理解这是怎么回事 这是最初的做法 我可以理解这里怎么
  • 如何防止在 ActiveX 方法调用期间重新进入 WPF 事件处理程序?

    我们从 WPF 和 STA 应用程序中调用 ActiveX 组件上的方法 此调用是通过以下方式后期绑定执行的 res ocx GetType InvokeMember methodName flags null ocx args 其中 oc
  • WPF - 位图效果上的编程绑定

    我希望能够以编程方式将一些数据绑定到 a 上的依赖属性位图效果 对于像 TextBlock 这样的 FrameworkElement 有一个 SetBinding 方法 您可以通过编程方式执行这些绑定 例如 myTextBlock SetB
  • WPF 如何从 DataTemplate 访问控件

    我有一个包含网格的数据模板 网格内有一个组合框
  • 如何从作为 UWP 运行的 WPF 应用程序处理文件激活?

    我有一个WPF我想要处理文件激活的应用程序 我找到了通过向注册表添加特定值来解决问题的解决方案 问题是最终的应用程序应该是UWP应用程序 我正在使用桌面桥来执行此操作 如果应用程序运行为UWP 它无法到达注册表来设置这些特定值 有没有其他方
  • 如何在PYQT中创建按钮点击

    我在 PyQT 中创建按钮单击时遇到了一些问题 当我创建如下按钮的点击时 这张图片无法保存 cv SetImageROI image pt1 0 pt1 1 pt2 0 pt1 0 int pt2 1 pt1 1 1 if self But

随机推荐

  • 为什么我的老化 Django 1.3.1 站点在迁移到新服务器后显示“TemplateDoesNotExist at /admin/”?

    我在现已受到攻击的服务器上有一个 Django v1 3 1 站点 以前位于 Python v2 7 3 上 我已经能够通过旧管理站点的缓存重建大部分内容 但在新服务器实例 Python v2 7 12 上重新安装 Python 和 Dja
  • 如何在代码中设置背景图像?

    如果我想将图像设置为文本框的背景 我可以在 axml 中使用以下代码
  • 如何创建一个饼图来显示每个人注册的商品数量?

    在我的项目中 我想在饼图中显示每个员工在系统中注册了多少个机构 机构表包含一个外键 其中包含注册该机构的员工的 ID 因此每个机构都有一个与其关联的员工 我构建了以下代码 但无法进一步 etc String query SELECT i i
  • Android 相机在横向模式下拉伸

    我正在编写的应用程序需要相机功能 因此 为了了解如何操作相机 我遵循了以下脚本 http developer android com resources samples ApiDemos src com example android ap
  • 在 Visual Studio 中调试接受命令行参数的 Windows 窗体应用程序

    我在 Windows 窗体中创建了应用程序 用于检查它是否包含特定的命令行参数并采取相应的操作 现在我想使用不同的命令行参数测试 调试我的代码 我通过单击我的项目并选择 属性 调试 来输入命令行参数 但是当我开始调试时 我收到以下消息 当前
  • 如何重新排序主键?

    我在 表类别 中删除了一行 第 20 行 请告诉我如何重新排序 catid 主键 此时已是19点21分 Thanks 你不能 你能得到的最接近的是truncate table 这将删除表并重新创建它 这意味着您将丢失其中的所有数据 并且 I
  • IMFSinkWriter 中的错误?

    我用两种方式实现了编码器 1 基于SDK Transcoder示例 该示例使用拓扑和转码配置文件 2 基于IMFSourceReader和IMFSinkWriter Sinkwriter将样本传递给Sourcewriter进行转码 我在 W
  • 如何在android中使用身份验证Uid从FirebaseUser获取用户名?

    我通过使用注册了一个用户createUserWithEmailAndPassword 并使用登录signInWithEmailAndPassword 方法 现在 当我登录用户时 我需要获取存储在用户节点中的用户名 手机 我可以获取每个用户的
  • PHP 函数替换第 (i) 个位置的字符

    PHP 中是否有一个函数可以接收字符串 数字 i 和一个字符 x 然后替换位置 i with x 如果没有 有人可以帮助我实施吗 str bar str 1 A echo str prints bAr 或者你可以使用库函数substr re
  • Python 3.5 中包导入失败

    我有以下文件夹结构 main main py io init py foo py 在Python 2 7中我会写以下内容main py import io foo or from io foo import 而在 Python 3 5 中我
  • 在 java 7 中编译时出现名称冲突编译错误,但在 java 5 中工作正常

    public interface Expression public interface ArithmeticExpression extends Expression public class StaticMethodDemo publi
  • 如何使用 Swift 2.0 动态转换为在字符串中命名的类型?

    我需要将返回值转换为需要保持动态的特定类型 例如 let cellType CellTypeToBeResolved cell tableView dequeueReusableCellWithIdentifier myID as Cell
  • 使用 C++ 或 C 处理图像

    首先 我是一个初学者 好的 我已阅读相关答案和问题 但请帮助我解决这个问题 如何在 C 中打开 JPEG 图像文件 将其转换为灰度图像 获取其直方图 将其调整为较小的图像 裁剪其特定区域 或显示其特定区域 对于这些任务 一般来说 C 还是
  • UIWebView 搜索 [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 在文本中搜索文本字符串的最佳方法是什么UIWebView 我认为最好的做法是 创建一个 javascript 函数来查找您的文本 Use the
  • 搜索多个列表以查找缺失的条目

    我有 3 个列表 我在这里将它们简单化 字母列表 A B C 数字列表 1 23 Mixed A 1 A 2 B 2 B 3 C 1 C 3 我需要知道缺少什么 A 3 B 1 C 2 字母列表大约有 85 个条目号码列表大约有 500 个
  • 为什么 arc4random 返回奇怪的值?

    我在 iOS 应用程序的函数中调用 arc4random 来生成 5 到 6 之间的随机值 double num for int i 0 i lt 3 i num arc4random 11 5 NSLog 0 0f num 我从控制台得到
  • 长整型值 Objective-C

    我在 NSString 中有长整数值 例如 2705758126 当我尝试显示它时 NSLog i myValue integerValue 它返回 2147483647 如何显示 比较等这个长整数 Try with NSLog lld m
  • 删除 Vim 中行前的所有任意空格

    我编写了一个用于解析 XML 标签的插件 标签内的内容是缩进的 当我将解析的字符串复制到文件中时 它会变得像 Example line This is part of the parsed line Thats goes one End o
  • 为什么 bootstrap input-group 和 input-group-addon 会分开?

    我在表单水平 div 中有一个输入组 它在大屏幕上看起来很棒 它看起来也很棒bootply http www bootply com JHvCfPAYoT 但是每当我开始调整屏幕大小时 表单就会换行 这是可以的 但 input group
  • WPF自定义按钮最佳方法

    我想创建一个自定义Button在 WPF 内部 当然 该按钮将是一个用户控件 它将包含许多视觉元素 如描边 高光 阴影 发光 图像等 问题是 如果我使用 DependencyProperties 并将它们绑定在 XAML 中 我将无法在 D