【问题标题】:WPF: refreshing value of a computed field in an item of an ObservableCollectionWPF:刷新 ObservableCollection 项目中计算字段的值
【发布时间】:2015-01-14 14:54:48
【问题描述】:

我的 WPF ObservableCollection 有问题。

我有一个绑定到 ListView 的 ObservableCollection (_additionalCosts),其中包括一个基于项目中其他属性的值的只读计算字段,并且至关重要的是,另一个下拉列表的值。

当我更改下拉列表中的选定项时,我希望刷新计算字段,目前它没有这样做。

我的视图类如下所示:

[Serializable]
public class BookingView : ViewBase
{
    private ObservableCollection<AdditionalCostView> _additionalCosts = new ObservableCollection<AdditionalCostView>();

    //..other members

    public ReferenceDataView SellPriceCurrency
    {
        get { return _sellPriceCurrency; }
        set
        {
            this.OnPropertyChanged("SellPriceCurrency");
        }
    }

    //..other members
}

AdditionalCostView 的项目如下所示:

[Serializable()]
public class AdditionalCostView : ViewBase, IEquatable<AdditionalCostView>
{
    //..other members
    private decimal? _margin;

    public decimal? Margin
    {
        get
        {
            if (_charterSellPriceCurrency == null)
                return null;

            if (_sellPrice.HasValue && _buyPrice.HasValue)
            {
                return _exchangeRateConverter.ConvertUsingExchangeRate(1, _sellPriceCurrency.Name, _charterSellPriceCurrency.Name, _sellPrice.Value) -
                       _exchangeRateConverter.ConvertUsingExchangeRate(1, _buyPriceCurrency.Name, _charterSellPriceCurrency.Name, _buyPrice.Value);
            }

            return null;
        }
    }

    //..other members
}

如果您需要更多代码,请告诉我。

我该如何做到这一点?

【问题讨论】:

  • 您的计算域是否实现了 INotifyPropertyChanged?也许您可以发布一些代码?
  • 好的,我已经添加了一些代码
  • 只需在 AdditionalCostView 类中实现 INotifyPropertyChanged 并从其他相关属性中调用显示属性的名称。
  • 你能指导我看一个如何实现这个的简洁例子吗?我有点害怕 INotifyPropertyChanged 已经三年没有做 WPF了!
  • INotifyPropertyChanged 几乎是 WPF 中最不可怕的部分。 :) 你可以做到!

标签: c# wpf data-binding observablecollection


【解决方案1】:

这是一个简单的示例,说明如何在 WPF 中使用计算字段。假设我们有一个属性Result,其值取决于另一个属性Multiplier。这就是你如何让这个场景工作...请注意你必须实现INotifyPropertyChanged 接口才能让它工作:

public string Result
{
    get { return Multiplier * someFixedValue; }
}

public string Multiplier
{
    get { return multiplier; }
    set { multiplier = value; NotifyPropertyChanged("Multiplier", "Result"); }
}

...

protected override void NotifyPropertyChanged(params string[] propertyNames)
{
    if (PropertyChanged != null)
    {
        foreach (string propertyName in propertyNames)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

这样,每次Multiplier属性更新时,Result属性也会在UI中更新。

【讨论】:

  • 但是元素中的其他属性没有改变——它是一个正在改变的下拉列表。这应该会触发列表视图中的边距更新。
  • 这就是重点......您需要更改元素中的其他属性。您可以通过将另一个属性放入元素并将其数据绑定到 ComboBox.SelectedItem 来做到这一点,以便在 UI 中更改所选项目时更新。
【解决方案2】:

我想您的 ViewBase 类实现了 INotifyPropertyChanged。 根据您的代码,我了解到每次 _charterSellPriceCurrency_sellPrice_buyPrice 更改时,都必须重新计算 Margin 属性。

此代码仅考虑 _charterSellPriceCurrency 更改,但很容易将其扩展到其他字段。

private YourType _charterSellPriceCurrency;
private Nullable<decimal> _margin;

public YourType CharterSellPriceCurrency 
{
    get
    {
        return _charterSellPriceCurrency;
    }
    private set
    {
        if (value != _charterSellPriceCurrency)
        {
            _charterSellPriceCurrency = value;
            OnPropertyChanged("CharterSellPriceCurrency");
            CalculateMargin();
        }
    }
}

public Nullable<decimal> Margin
{
    get
    {
        return _margin;
    }
    private set
    {
        if (value != _margin)
        {
            _margin = value;
            OnPropertyChanged("Margin");
        }
    }
}

private void CalculateMargin()
{
    if (_charterSellPriceCurrency == null)
    {
        Margin = null;
        return;
    }

    if (_sellPrice.HasValue && _buyPrice.HasValue)
    {
        Margin = _exchangeRateConverter.ConvertUsingExchangeRate(1, _sellPriceCurrency.Name, _charterSellPriceCurrency.Name, _sellPrice.Value) -
                _exchangeRateConverter.ConvertUsingExchangeRate(1, _buyPriceCurrency.Name, _charterSellPriceCurrency.Name, _buyPrice.Value);
        return;
    }

    Margin = null;
}

关键是您必须通知 UI Margin 属性已更改,无论它是否为只读属性,如果更改,您必须引发事件。否则 UI 无法知道它已被重新计算。

【讨论】:

  • 但是当从下拉列表中选择不同的项目时,Margin 属性没有更新。保证金只有在下拉列表有值时才会计算,你看,所以当应用货币时,应该计算保证金。
  • 您有 2 个解决方案:1)您可以处理 ComboBox 的 SelectionChanged Event。在事件处理程序中,您可以调用CalculateMargin 方法。 2) 您可以将 ComboBox 的 SelectedItem 属性绑定到 BookingView 类的属性。当第二个属性发生变化时,您可以调用CalculateMargin 方法(在这种情况下不能是私有的)。
猜你喜欢
  • 2016-05-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-11
  • 2016-06-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多