WPF双向数据绑定到可观察集合中的自定义数据类型

本文关键字:集合 定义数据类型 观察 数据绑定 WPF | 更新日期: 2023-09-27 18:22:08

我正在尝试数据绑定到WPF中的自定义数据类型属性FormulaField。我不明白是我错过了什么,还是我想做的事情做不到?

我遵循了绑定到基元的约定,发现它不起作用,FormulaField属性没有更新。我还注意到,自定义数据类型集方法永远不会被命中。我正在使用MVVM。

A型号:

 public class OBQModel : NotificationObject
    {    
        private FormulaField _tovLitres;
        public FormulaField TOVLitres
        {
            get
            {
                if (_tovLitres.UsesFormula)
                {
                    _tovLitres.Value = ConversionHelper.USBarrelsToLitres(_tovBarrels);
                }
                return _tovLitres;
            }
            set
            {
                _tovLitres = value;
                RaisePropertyChanged("TOVLitres");
            }
        }
}

NotificationObject实现INotifyPropertyChanged:

public abstract class NotificationObject : DependencyObject, INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        protected void RaisePropertyChanged<T>(Expression<Func<T>> action)
        {
            var propertyName = GetPropertyName(action);
            RaisePropertyChanged(propertyName);
        }
        private static string GetPropertyName<T>(Expression<Func<T>> action)
        {
            var expression = (MemberExpression)action.Body;
            var propertyName = expression.Member.Name;
            return propertyName;
        }
        protected internal void RaisePropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

FormulaField如下所示:

public class FormulaField
{
    public bool UsesFormula { get; set; }
    public double Value { get; set; }
}

编辑在FormulaField中实现INotifyPropertyChanged会导致堆栈溢出。。。

public class FormulaField : INotifyPropertyChanged
    {
        public bool UsesFormula { get; set; }
        public double Value
        {
            get
            {
                return Value;
            }
            set
            {
                Value = value;
            }
        }
        public event PropertyChangedEventHandler PropertyChanged;
        // Create the OnPropertyChanged method to raise the event 
        protected void OnPropertyChanged(string name)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(name));
            }
        }
    }

模型位于ViewModel中的ObservableCollection中。

视图图示:

<StackPanel>
    <DataGrid ItemsSource="{Binding OBQModelCollection}">    
     <DataGrid.Columns>
      <DataGridTemplateColumn Header="new TOV (L)" Width="100">
       <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
         <TextBox BorderThickness="0" 
                  Text="{Binding TOVLitres.Value, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>
        </DataTemplate>
       </DataGridTemplateColumn.CellTemplate>
      </DataGridTemplateColumn>
     </DataGrid.Columns>
    </DataGrid>
</StackPanel>

WPF双向数据绑定到可观察集合中的自定义数据类型

根据您所写的内容,您正在"LiquidGOVLitres"上引发INPC,它似乎没有出现在您的代码列表中,但您绑定到了"TOVLitres"。

修复这种不一致将有所帮助,但如果您希望对其成员的更改成为UI的一部分,则还需要在FormulaField上实现INPC。

ETA:在对代码列表进行澄清编辑后,剩下的任务是在FormulaField类上实现INPC,并相应地引发事件。

此外,如果你使用4.5,你可以调查新的成员信息类,这有助于避免在INPC中使用魔术串。

最后,为了语义清晰,将"Value"重命名为"FormulaValue"也无妨。。。

为了避免递归,请尝试此模型。。。

    private double _value;
    public double Value
    {
        [DebuggerStepThrough]
        get { return _value; }
        [DebuggerStepThrough]
        set
        {
            if (Math.Abs(value - _value) > Double.Epsilon)
            {
                _value = value;
                OnPropertyChanged("Value");
            }
        }
    }