WPF 样式设置器不工作

2023-12-09

我有一个包含组合框的自定义用户控件。我添加了一个 ComboBoxWidth 依赖属性,以允许开发人员根据需要设置宽度。使用样式设置器,我想将所有这些组合框的宽度设置为另一个用户控件上的相同值,以保持大小一致性。但是,它不起作用。如果我在每个控件上单独设置大小,它就会起作用。当在样式设置器中指定大小时,它将被忽略。如果我将属性字符串从“ComboBoxWidth”更改为“Width”,则所有控件的整个宽度都会更改。所以,看起来样式格式是正确的。我错过了什么吗?这是我第一次尝试将样式应用到我自己的自定义依赖属性。

注意:AngleUserControl 基于通用用户控件(不包括任何在代码中创建的 xaml 控件)。 ComboBoxWidth 探测器位于通用基类中。我不确定这是否与此有关。

样式代码(在包含多个 AngleUserControl 控件的用户控件中):

<UserControl.Resources>
    <Style TargetType="wpfControls:AngleUserControl">
        <Setter Property="ComboBoxWidth" Value="400"/>
    </Style>
</UserControl.Resources>

单元控制库:

/// <summary>
/// Control that displays value in different units depending on selected unit type.
/// </summary>
/// <typeparam name="TSelectionTypeEnum">The enumeration type for all the available units.</typeparam>
/// <typeparam name="TConverterType">The MultiValueConverter that converts the value between the different types of units.</typeparam>
/// <typeparam name="TValueType">The underlying type of the stored value.</typeparam>
public class UnitControlBase<TSelectionTypeEnum, TConverterType, TValueType> : UserControl
    where TSelectionTypeEnum : struct, IConvertible
    where TConverterType : IMultiValueConverter, new()
{
    #region Private Fields

    // Metadata for the dependency properties.
    private static FrameworkPropertyMetadata valuePropertyMetadata = new FrameworkPropertyMetadata(default(TValueType));
    private static FrameworkPropertyMetadata valueTypePropertyMetadata = new FrameworkPropertyMetadata(default(TSelectionTypeEnum));
    private static FrameworkPropertyMetadata displayValueTypePropertyMetadata = new FrameworkPropertyMetadata(default(TSelectionTypeEnum));
    private static FrameworkPropertyMetadata comboBoxWidthPropertyMetadata = new FrameworkPropertyMetadata(0.0);
    private static FrameworkPropertyMetadata valueFormatPropertyMetadata = new FrameworkPropertyMetadata(string.Empty);

    #endregion

    #region Constructor

    /// <summary>
    /// Constructor
    /// </summary>
    public UnitControlBase()
    {
        ValueFormat = "#,##0.00";
        ComboBoxWidth = 75.0;

        // Create main grid and add to control.
        Grid mainGrid = new Grid();
        mainGrid.Name = "LayoutRoot";
        this.AddChild(mainGrid);

        // Create grid columns.
        ColumnDefinition col1 = new ColumnDefinition();
        col1.Width = GridLength.Auto;
        ColumnDefinition col2 = new ColumnDefinition();
        mainGrid.ColumnDefinitions.Add(col1);
        mainGrid.ColumnDefinitions.Add(col2);

        // Create the text box that will display the value.
        Label displayValueLabel = new Label();
        displayValueLabel.Name = "DisplayValueLabel";
        Grid.SetColumn(displayValueLabel, 0);
        mainGrid.Children.Add(displayValueLabel);

        // Bind to the multi-value converter that will convert between the types.
        MultiBinding mb = new MultiBinding();
        mb.Converter = new TConverterType();
        mb.Bindings.Add(new Binding("Value") { Source = this });
        mb.Bindings.Add(new Binding("ValueType") { Source = this });
        mb.Bindings.Add(new Binding("DisplayValueType") { Source = this });
        mb.Bindings.Add(new Binding("ValueFormat") { Source = this });
        displayValueLabel.SetBinding(Label.ContentProperty, mb);
        displayValueLabel.HorizontalContentAlignment = System.Windows.HorizontalAlignment.Right;            

        // Create the combo box that will display selected unit.
        ComboBox displayValueComboBox = new ComboBox();
        displayValueComboBox.Name = "DisplayValueComboBox";
        displayValueComboBox.SetBinding(ComboBox.WidthProperty, new Binding("ComboBoxWidth") { Source = this });
        Grid.SetColumn(displayValueComboBox, 1);
        mainGrid.Children.Add(displayValueComboBox);

        // Bind available units and selected units.
        displayValueComboBox.ItemsSource = Enum.GetValues(typeof(TSelectionTypeEnum));
        displayValueComboBox.SetBinding(ComboBox.SelectedItemProperty, new Binding("DisplayValueType") { Source = this });
    }

    #endregion

    #region Dependency Properties

    /// <summary>
    /// Value Dependency Property
    /// </summary>
    public static readonly DependencyProperty ValueProperty =
        DependencyProperty.Register("Value", typeof(TValueType), typeof(UnitControlBase<TSelectionTypeEnum, TConverterType, TValueType>), valuePropertyMetadata);

    /// <summary>
    /// Value Type Dependency Property
    /// </summary>
    public static readonly DependencyProperty ValueTypeProperty =
        DependencyProperty.Register("ValueType", typeof(TSelectionTypeEnum), typeof(UnitControlBase<TSelectionTypeEnum, TConverterType, TValueType>), valueTypePropertyMetadata);

    /// <summary>
    /// Display Value Type Dependency Property
    /// </summary>
    public static readonly DependencyProperty DisplayValueTypeProperty =
        DependencyProperty.Register("DisplayValueType", typeof(TSelectionTypeEnum), typeof(UnitControlBase<TSelectionTypeEnum, TConverterType, TValueType>), displayValueTypePropertyMetadata);

    /// <summary>
    /// Combo Box Width Dependency Property
    /// </summary>
    public static readonly DependencyProperty ComboBoxWidthProperty =
        DependencyProperty.Register("ComboBoxWidth", typeof(double), typeof(UnitControlBase<TSelectionTypeEnum, TConverterType, TValueType>), comboBoxWidthPropertyMetadata);

    /// <summary>
    /// Value Format Dependency Property
    /// </summary>
    public static readonly DependencyProperty ValueFormatProperty =
        DependencyProperty.Register("ValueFormat", typeof(string), typeof(UnitControlBase<TSelectionTypeEnum, TConverterType, TValueType>), valueFormatPropertyMetadata);

    #endregion

    #region Public Properties

    /// <summary>
    /// The underlying stored value.
    /// </summary>
    public TValueType Value
    {
        get
        {
            return (TValueType)GetValue(ValueProperty);
        }
        set
        {
            SetValue(ValueProperty, value);
        }
    }

    /// <summary>
    /// The unit type for the underlying stored value.
    /// </summary>
    public TSelectionTypeEnum ValueType
    {
        get
        {
            return (TSelectionTypeEnum)GetValue(ValueTypeProperty);
        }
        set
        {
            SetValue(ValueProperty, value);
        }
    }

    /// <summary>
    /// The unit type for the displayed value.
    /// </summary>
    public TSelectionTypeEnum DisplayValueType
    {
        get
        {
            return (TSelectionTypeEnum)GetValue(DisplayValueTypeProperty);
        }
        set
        {
            SetValue(DisplayValueTypeProperty, value);
        }
    }

    /// <summary>
    /// Width of combo box displaying available units.
    /// </summary>
    public double ComboBoxWidth
    {
        get
        {
            return (double)GetValue(ComboBoxWidthProperty);
        }
        set
        {
            SetValue(ComboBoxWidthProperty, value);
        }
    }

    /// <summary>
    /// The format of the displayed value.
    /// </summary>
    public string ValueFormat
    {
        get
        {
            return (string)GetValue(ValueFormatProperty);
        }
        set
        {
            SetValue(ValueFormatProperty, value);
        }
    }

    #endregion
}

AngleUserControl.cs

/// <summary>
/// Control allowing user to display a value in degrees, radians, or semicircles.
/// </summary>
public class AngleUserControl : UnitControlBase<AngleSelectionType, AngleMultiValueConverter, double>
{
    #region Constructor

    /// <summary>
    /// Constructor.
    /// </summary>
    public AngleUserControl()
    {
        this.ComboBoxWidth = 175.0;
    }

    #endregion
}

依赖属性的所谓“本地值”,例如

this.ComboBoxWidth = 175.0;

具有比样式设置器中的值更高的值优先级,例如

<Setter Property="ComboBoxWidth" Value="400"/>

因此样式设置器没有任何作用。

您应该通过覆盖依赖属性元数据来分配新的默认值:

public class AngleUserControl : ...
{
    static AngleUserControl()
    {
        ComboBoxWidthProperty.OverrideMetadata(
            typeof(AngleUserControl),
            new PropertyMetadata(175d));
    }
}

See 依赖属性值优先级以供参考。

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

WPF 样式设置器不工作 的相关文章

随机推荐

  • 如何将文本添加到活动的 UITextField

    我有几个UITextField的和一个UIButton 如果我点击UIButton 我想在活动中放置一些静态文本UITextField 所以像这样 IBAction func buttonEen sender UIButton active
  • 将文本转换委托给“插件”Android 应用程序,事先未知

    Context 我们的应用程序向用户显示 HTML 抽认卡 我们添加了几层 过滤器 来满足不同的用户群体 为了满足chess爱好者 我们转换任何 FEN rnbqkbnr pp1ppppp 8 2p5 4P3 5N2 PPPP1PPP RN
  • PyQt - 如何打开/关闭拼写检查

    我使用以下内容作为编辑器拼写检查器的基础 我想制作一个自动拼写检查按钮 按下该按钮将使拼写检查器工作 而未按下时 拼写检查器不应突出显示或建议任何内容 您知道类似于 LibreOffice OpenOffice 自动拼写检查工具栏按钮吗 我
  • 可可-Applescript NSOpenPanel?

    我该如何做NSOpenPanel在可可 Applescript 中 有什么好的教程吗 我熟悉 Applescript 但不太熟悉 Cocoa 部分 我需要一个nib对于 NSOpenPanel 我正在做一个自动操作 看我之前的问题 肖恩 斯
  • 如何在对话期间以编程方式将号码输入到 Android 中的电话应用程序屏幕中

    我想通过我的 Android 程序在对话期间以编程方式将号码输入到 Android 手机的电话应用程序中 像这样的操作 1 打开拨号键盘并 2 键入号码 例如 当您拨打该电话号码并且该电话号码有用于呼叫目的地的分机电话号码时 例如 电话号码
  • Tkinter 中 GStreamer 的视频输出?

    有谁知道我将如何使用 tkinter 窗口作为 python 内的视频接收器 管道的输出 我已经找到了许多其他 GUI 系统的方法 但我不想必须同时使用 tkinter 和其他东西 xxx 预先感谢 x 这对我在 Windows 32 位上
  • 对象必须实现 IConvertible

    对象必须实现 IConvertible 描述 执行当前 Web 请求期间发生未处理的异常 请查看堆栈跟踪以获取有关错误及其在代码中的来源的更多信息 异常详细信息 System InvalidCastException 对象必须实现 I敞篷车
  • 如何在Python中将文本中每个句子的开头大写? [复制]

    这个问题在这里已经有答案了 我想创建一个函数 将一个文本字符串作为输入 并且我想将标点符号后面的每个字母大写 问题是 字符串不像列表那样工作 所以我真的不知道该怎么做 我尝试这样做 但它似乎不起作用 def capitalize strin
  • iOS相机焦点值

    有什么办法可以从具有自动对焦功能的 iPhone 相机中获取焦点值吗 我想使用这些数据来计算 iPhone 到焦点对象的距离 显然这是一个老问题 但由于自 iOS8 以来有一个获取 镜头值 的选项 它应该出现在这里 从iOS 8开始你可以通
  • cx_Freeze 错误:resource_filename() 仅支持 .egg,不支持 .zip

    我有一个完全工作的基于 wxpython 的应用程序 全部用 Python 编写 我想制作一个exe 所以我使用了cxFreeze 在构建过程中 有许多模块似乎丢失了 有时这应该不会造成问题 但是当我运行应用程序时 它给了我来自 MySQL
  • 函数隐藏和重载的区别

    我找不到函数隐藏和重载之间的任何区别 由于函数隐藏是派生类中存在的函数并隐藏基类的函数 两者的函数名称相同 重载 派生类和基类具有相同的名称但不同的签名 class A void print int class B public A voi
  • ant build 中使用 aapt 进行紧缩/资源打包使用其他项目的缓存

    我有两个使用通用库的 Android 应用程序 每个项目都为启动屏幕和其他一些项目定义了自己的背景图像 这些图像在两个应用程序中具有相同的名称 当我从 Eclipse 构建 运行时 每个应用程序都使用正确的背景图像 但是 当我运行 ant
  • jqueryposition() 在 safari 和 chrome 中无法正常工作

    我以前曾见过这个问题一两次 但从未有过适用于我的问题的答案 据我所知 我有一个单击链接时出现的工具提示 我根据链接的位置设置工具提示的位置 如下所示 tooltip css left this position left 这在 FF IE
  • 比较两个数组并用第三个数组中的值替换重复项

    var array1 a b c d var array2 a v n d i f var array3 1 2 3 4 5 6 刚开始学习Javascript 我不知道如何比较array2给那些在array1如果是这样 请将其替换为相应的
  • 一个简单的 SQL Select 查询来抓取社交图中所有有联系的人?

    爬取社交图谱的最短或最快的 SQL 选择查询或 SQL 过程是什么 想象一下我们有这张表 UId FriendId 1 2 2 1 2 4 1 3 5 7 7 5 7 8 5 9 9 7 我们这里有两个人 我正在谈论一个 sql 查询或过程
  • 嵌入式 Python 无法使用 NumPy 指向 Python35.zip - 如何修复?

    好的 这是来自 Python 网站的基本示例 用于简单说明runpy exe运行下面的 Python 脚本 引用 Python 包含并链接到后 在 x64 Windows 上使用 Visual Studio 2015 可以正常工作pytho
  • Spring Data mongodb-复制集合

    我将 spring 数据与 mongodb 一起使用 我想使用代码而不是命令行将文档从一个集合复制到另一个集合 有没有办法在不循环所有文档并执行 插入 的情况下执行此操作 除非像这样的命令一样使用它 mongoTemplate execut
  • 错误:超时间隔必须小于 2^32-2。参数名称: dueTm

    我的班级模型中有一对多关系 例子 单个角色可以附加多个权限 因此有两张表 一张来自角色 一张用于每个角色的权限 现在我有一个角色类 该角色类又具有作为该类成员的权限列表 当我需要进行更新时 我实例化一个transactionscope对象
  • 将文本添加到 div(或其他元素)的底部 - 模拟聊天控制台

    我有一个 div 应该在文本输入到输入框中时收集文本 现在它只是重现输入 但稍后它应该产生半智能响应 我希望文本出现在 div 的底部 渐变的暗端 我希望新文本始终位于底部 旧文本始终位于上部滚动区域的灰色区域 In other words
  • WPF 样式设置器不工作

    我有一个包含组合框的自定义用户控件 我添加了一个 ComboBoxWidth 依赖属性 以允许开发人员根据需要设置宽度 使用样式设置器 我想将所有这些组合框的宽度设置为另一个用户控件上的相同值 以保持大小一致性 但是 它不起作用 如果我在每