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>
根据您所写的内容,您正在"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");
}
}
}