【问题标题】:How to use a Property which depends the value of another property?如何使用依赖于另一个属性值的属性?
【发布时间】:2020-10-19 14:10:17
【问题描述】:

有一个自定义属性,它依赖于其他系统属性的值,以便在 WinForms 中正确初始化。

让我举个例子。让我们创建一个类WhateverButton: Button,并使用一个名为MyExampleProperty 的自定义属性和系统控件属性让我们使用this.Height,它来自控件的大小。

公共类 WhatButton : 按钮
{
   // 成员
   私有 int m_myExampleProperty;

   // 构造函数
   公共随便按钮(){
      m_myExampleProperty = 1;
   }
    
    // 财产
    公共 int MyExampleProperty
    {
      获取 => m_myExampleProperty;
      放
      {
        m_myExampleProperty= 值 > (this.Height / 2F) ? 1:值;
      }
    }

    // 每次 Size 改变时,更新属性
    受保护的覆盖无效 OnSizeChanged (EventArgs e)
    {
      base.OnSizeChanged (e);

      m_myExampleProperty = m_myExampleProperty > this.Height / 2F ? 1:m_myExampleProperty;

    }

}

在表单中添加WhateverButton(大小大于默认值)。 WinForms 按字母顺序生成元素(按钮、标签、文本框等),例如:

this.buttonWhatever.Location = new System.Drawing.Point (413, 57); // L this.buttonWhatever.Margin = new System.Windows.Forms.Padding (3, 4, 3, 4); // 米 this.buttonWhatever.MyExampleProperty= 30; // 米 ... // 其他属性 this.buttonWhatever.Name = "我的元素"; // 否 this.buttonWhatever.Size = new System.Drawing.Size (50, 80); // 小号 this.buttonWhatever.Text = "我的元素"; // T

通过表单 UI 更改属性MyExampleProperty 值后,它似乎可以工作,但在保存表单(Ctrl+S)后,属性返回到 1。

Debugging 可能会发现每次保存表单时,所有元素都会按该顺序再次创建。当MyExampleProperty 的时间到达时,Size 属性尚未创建,它将假定默认的Height 和Width,当然,该属性的值将是错误的。如果我只是重命名 MyExampleProperty 到任何其他名称,在此示例中将放置在 Size 属性之后,它将起作用。也许我错过了一些我不知道要搜索的东西。

【问题讨论】:

  • 这是一个很奇怪的属性,你看...如果我将它设置为某个值,然后尝试Console.WriteLine 它,我可能无法获得我刚刚设置的值。是否需要以这种方式拥有它?因为最好将它分成两个属性,一个是可以获取和设置的常规属性,另一个是使用高度计算其值的 get-only 属性。
  • 是的。我的依赖是 Size 属性。
  • 我不是在问“对 Size 属性的依赖”是否是必需的。我在问“设置一个值然后没有得到相同的值”是否是一个要求。你仍然可以拥有一个取决于大小的属性,但它不需要有这种奇怪的行为......
  • 第一个选项效果很好!感谢您的宝贵时间。

标签: c# visual-studio winforms


【解决方案1】:

你的属性的问题是,如果在设置属性的时候控件的高度不合适,那么传递给setter的值就永远丢失了。

因此,在 setter 中,您应该始终将 value 分配给支持字段,并检查 getter 中的高度:

public int MyExampleProperty
{
  get => m_myExampleProperty > (this.Height / 2F) ? 1 : m_myExampleProperty;
  set
  {
    m_myExampleProperty = value;
  }
}

这样,您甚至不需要处理SizeChanged 事件!

或者更好,写成两个属性:

public int MyExampleProperty { get; set; }
public int MyExamplePropertyThatChangesWithSize => 
    MyExampleProperty > (this.Height / 2F) ? 1 : MyExampleProperty;

...因为你没有得到你刚刚设置的值的属性是完全出乎意料的并且可能会令人困惑。

【讨论】:

  • 只有最后一部分将 Size 设置为一个很大的值......它刚刚停止了 Visual Studio 大声笑。初始按钮太大。
  • @PauloGuimarães 是这样吗?好吧。我已经删除了那部分。似乎无论如何都不需要这种奇怪的行为......
猜你喜欢
  • 2011-07-22
  • 1970-01-01
  • 2011-12-01
  • 2020-05-17
  • 1970-01-01
  • 2012-08-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多