【问题标题】:Can INotifyPropertyChanged affect derived functions [duplicate]INotifyPropertyChanged 会影响派生函数吗?
【发布时间】:2017-09-24 19:36:35
【问题描述】:

更新:我的问题最初涉及格式问题以及从多个其他属性“派生”的属性。我认为这是相同的情况,但正如您从 Fabios 的回答中看到的那样,情况并非如此。我稍微改变了这个问题,以明确它不是只是格式。

我正在使用带有单向数据绑定的 WinForms,并使用 INotifyPropertyChanged 来更新表单。但我无法准确弄清楚它如何影响派生函数。例如,假设我有一个以小数形式返回价格的函数:

public decimal price 
{
    get { return _price; }
    set 
    { 
        // Set price and notify that it was changed
        _price = value; 
        InvokePropertyChanged(new PropertyChangedEventArgs("price");
    }
}

另一个属性负责货币代码,也可以更改:

public decimal currency
{
    get { return _currency; }
    set
    {
        _currency = value;
       InvokePropertyChanged(new PropertyChangedEventArgs("currency");
    }
}

当价格或货币改变(设置)时,调用属性改变函数。但是,在我的 GUI 中显示它之前,我希望这个值被格式化并带有货币代码。所以我将数据绑定到派生函数:

public string formattedPrice
{
    get { return string.Format("{0:n0} {1}", price, currency)
}

更改pricecurrency 将如何影响formattedPrice?显然我一直在做自己的一些测试,但我似乎真的找不到逻辑? InvokepropertyChanged 函数定义如下:

public event PropertyChangedEventHandler PropertyChanged;
public void InvokePropertyChanged(PropertyChangedEventArgs e)
{
    PropertyChangedEventHandler handler = PropertyChanged;
    if (handler != null) handler(this, e);
}

【问题讨论】:

  • 许多方法来解决这个问题。有关几个选项,请参阅标记的重复项。就个人而言,我更喜欢让我的 INPC 属性完全不受自定义逻辑的影响。相反,我使用了一个基本实现,它允许 setter 挂钩回调,并在该回调中处理特定于属性的行为。然后对于您正在谈论的内容,在这样的回调中只需 设置“派生”属性(恕我直言,这是一个不幸的词选择,因为“派生”具有特定的、完全不相关的含义在 OOP 中)到一个新的值。是的,有更多的支持字段,但代码更简单。
  • @PeterDuniho - 我认为这个问题的具体情况更多地与格式值有关。您提供的“相关”答案会将 OP 和未来的读者引向错误的方向。
  • 所以这很快就从零变成了火箭科学:-)。我对“保持我的 INPC 属性完全不受自定义逻辑”的意思有点困惑。我对 C# 还有些陌生,所以我必须承认我不太确定我的 InvokePropertyChanged 函数是如何工作的。你能用代码展示一下吗?
  • @Noceo - 让我的 INPC 属性完全不受自定义逻辑的影响 - 通常意味着 setter 应该只做两件事:1. Update value; 2. Raise PropertyChanged event for this property.(此外,您可以检查新值相同的)。所有其他逻辑都应移到 setter 之外(例如为其他属性引发 PropertyChanged 事件,或计算其他属性或执行其他操作)如果您需要执行其他操作 - 那么您应该使用命令 (ICommand)。
  • 没有上下文,很难提出“正确”的方法。至少你可以在那个“不同的类”中“收听”PropertyChanged,并在“基础”类为你收听的属性提高PropertyChanged时提高自己的PropertyChanged

标签: c# winforms data-binding inotifypropertychanged


【解决方案1】:

您可以简单地在 setter 中为格式化值调用 PropertyChanged

public decimal price 
{
    get { return _price; }
    set 
    { 
        _price = value; 
        InvokePropertyChanged(new PropertyChangedEventArgs("price");
        InvokePropertyChanged(new PropertyChangedEventArgs("formattedPrice");
    }
}

但是,由于格式化值更多的是 UI(视图)责任 - 您可以使用 Binding.Format 事件将其移动到 Windows 窗体端,并保持 price 属性不变。

public decimal price 
{
    get { return _price; }
    set 
    { 
        _price = value; 
        InvokePropertyChanged(new PropertyChangedEventArgs("price");
    }
}

// In windows form
var priceBinding = new Binding("Text", sourceObject, "price", true);
priceBinding.Format += (sender, args) => 
{
    var price = (decimal)args.Value;
    args.Value = string.Format("{0:n0} EUR", price);
}

priceTextBox..DataBindings.Add(priceBinding);

更多关于Binding.Format Event

【讨论】:

  • 这就是我目前正在做的事情。我只是想知道是否有办法避免手动跟踪链接。在我给出的示例中,它非常简单,但在较大的程序中,链会变得更长(并且可能会出现分支),因此更难跟踪......
  • @Noceo - 检查更新的答案
  • 这很酷。实际上,我的问题是基于从一个或多个其他属性“派生”的格式和属性,因为我认为解决方案是相同的。但这至少解决了我的格式问题:-)。
猜你喜欢
  • 2020-05-30
  • 1970-01-01
  • 1970-01-01
  • 2021-09-18
  • 2017-04-26
  • 2022-01-24
  • 2010-09-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多