C# WPF双向数据绑定到可观察集合中的自定义数据类型
我正在尝试将数据绑定到WPF中的自定义数据类型属性C# WPF双向数据绑定到可观察集合中的自定义数据类型,c#,wpf,data-binding,mvvm,C#,Wpf,Data Binding,Mvvm,我正在尝试将数据绑定到WPF中的自定义数据类型属性FormulaField。我不明白我是否错过了什么,或者我想做的事情是否做不到 我遵循了我如何绑定到一个原语的惯例,发现它不起作用,FormulaField属性没有更新。我还注意到,自定义数据类型集方法从未被命中。我正在使用MVVM 模型: public class OBQModel : NotificationObject { private FormulaField _tovLitres; p
FormulaField
。我不明白我是否错过了什么,或者我想做的事情是否做不到
我遵循了我如何绑定到一个原语的惯例,发现它不起作用,FormulaField
属性没有更新。我还注意到,自定义数据类型集方法从未被命中。我正在使用MVVM
模型:
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
中实现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中的可观察集合
中
视图的图示:
<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>
根据您所写的内容,您正在“liquidGovlls”上提高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");
}
}
}
我不确定,但我认为问题在于您将文本绑定到FormulaField类的属性,而该属性不发送RaisePropertyChanged事件。尝试将其添加到“值”属性设置器。@Superforce尝试将什么添加到“值”属性设置器?是的,“FormulaField”类中有一个名为“值”的属性,文本框文本绑定到该属性。我认为您必须编辑他的setter以应用新值并添加RaisePropertyChanged事件。就像你对TOVLitres对象所做的那样。当我这样做时,我会得到一个堆栈溢出异常…闻起来像循环依赖是的,该属性与此无关。我将编辑我的问题,所以我这样做并得到堆栈溢出是的,因为“Value”(语句“Value=Value”)的setter调用“Value”的setter,这是一个递归调用。考虑使用支持字段,最好是私有的。啊,这就是私人的东西,非常感谢!这起作用了,你帮我了解了发生了什么
private double _value;
public double Value
{
[DebuggerStepThrough]
get { return _value; }
[DebuggerStepThrough]
set
{
if (Math.Abs(value - _value) > Double.Epsilon)
{
_value = value;
OnPropertyChanged("Value");
}
}
}