问题很简单:如何在不修改dataObject的情况下触发dataObject的更改,并在visual上看到这个更改?
DataObject:
ProductData : INotifyPropertyChanged
{
private ProductPartData myProductPartData;
public ProductPartData ProductPartData
{
get
{
return myProductPartData;
}
set
{
if (value != myProductPartData)
{
myProductPartData = value;
OnNotifyPropertyChanged("ProductPartData");
}
}
}
}
的DataTemplate:
<DataTemplate
DataType="{x:Type ProductData}"
>
<VisualProduct
ProductPartData="{Binding Path=ProductPartData, Mode=OneWay}"
/>
</DataTemplate>
现在我有一个VM:
product.OnNotifyPropertyChanged("ProductPartData");
问题: 即使在执行OnNotifyPropertyChanged时调用ProductPart的getter,也不会通知visual,因为它与ProductPartData的实例相同。
如何在不更改实例的情况下触发Visual看到的更改? 谢谢,
答案 0 :(得分:3)
丹尼尔,
一个解决方案是使用BindingExpression类的UpdateTarget()方法,这样无论如何都会刷新绑定的目标;当然,你的转换器也会被击中 - 如果有的话。由于我猜你没有访问产品中的visual,你可以使用附加属性,在它的回调中,你可以得到BindingExpression并在其上调用UpdateTarget()。
请注意,我使用简单的TextBlock作为数据对象的视觉效果。
public class BindingHelper
{
public static bool GetRefreshBinding(DependencyObject obj)
{
return (bool) obj.GetValue(RefreshBindingProperty);
}
public static void SetRefreshBinding(DependencyObject obj, bool value)
{
obj.SetValue(RefreshBindingProperty, value);
}
// Using a DependencyProperty as the backing store for RefreshBinding. This enables animation, styling, binding, etc...
public static readonly DependencyProperty RefreshBindingProperty =
DependencyProperty.RegisterAttached("RefreshBinding", typeof(bool), typeof(BindingHelper), new UIPropertyMetadata(false, OnRefreshBindingPropertyChanged));
static void OnRefreshBindingPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs ea)
{
TextBlock elem = o as TextBlock;
if (elem != null)
{
BindingExpression bEx = elem.GetBindingExpression(TextBlock.TextProperty);
if (bEx != null)
{
bEx.UpdateTarget();
}
}
}
}
此外,在您的数据对象中,您可以创建一个绑定到模板中附加属性的新bool属性(让我们将其命名为ShouldRefresh) - 这将触发AP的属性更改:
<DataTemplate DataType="{x:Type local:ProductData}">
<TextBlock Text="{Binding Path=Name, Converter={StaticResource BlankConverter}}"
local:BindingHelper.RefreshBinding="{Binding Path=ShouldRefresh}"/>
</DataTemplate>
因此,这样,只要您想通过绑定更新目标,就可以设置:
ShouldRefresh = !ShouldRefresh
在您的数据类中。
HTH。
答案 1 :(得分:1)
如果你引发一个PropertyChanged事件,并且该属性的新值等于WPF已经拥有的值,它将忽略你。你有几个选择:
“快速”方式是将属性设置为null,然后再次返回正确的值,确保每次都引发PropertyChanged事件。它很脏但每次都有效。
“正确”的方法是强制进行绑定刷新,如this post by Jaime Rodriguez中所述。因为你的视觉是数据模板化的,虽然让“dependencyObject”传入该帖子中的调用是有点棘手的。您最终可能需要使用this post by Josh Smith中讨论的模板的FindName方法。
答案 2 :(得分:1)
我们遇到了这种来自数据库并转换为DTO(数据传输对象)的数据的问题。
我们的DTO基类覆盖对象的方法,例如Equals()
和GetHashCode()
,如下所示:
public override Boolean Equals(Object obj)
{
// Null reference
if (null == obj)
return false;
// Same reference
if (Object.ReferenceEquals(this, obj))
return true;
EntityDTOBase<TEntity> entiteObj = obj as EntityDTOBase<TEntity>;
if (null == entiteObj)
return false;
else
return Equals(entiteObj);
}
public Boolean Equals(EntityDTOBase<TEntity> other)
{
// Null reference
if (null == other)
return false;
// Same reference
if (Object.ReferenceEquals(this, other))
return true;
// No Id: cannot be compared, return false
if (this.id == TypeHelper.DefaultValue<long>())
return false;
// Id comparison
if (this.id != other.id)
return false;
return true;
}
public override Int32 GetHashCode()
{
return this.id.GetHashCode();
}
所以问题是当我们从数据库再次加载相同的实体时,因为ID是相同的,一些绑定没有正确更新。
通过添加额外的虚拟EqualsExtended()
方法来避免此特定问题,默认实现只返回true
:
protected virtual Boolean EqualsExtended(EntityDTOBase<TEntity> other)
{
return true;
}
public Boolean Equals(EntityDTOBase<TEntity> other)
{
/// Same code as before (except last line):
return EqualsExtended(other);
}
现在在我们的DTO类的任何实现中,我们可以添加一些逻辑以使Equals()
在某些情况下返回false,例如通过在从数据库中检索数据时添加时间戳:
protected override Boolean EqualsExtended(EntityDTOBase<Act> other
{
if (this.Timestamp != other.Timestamp)
{
return false;
}
return true;
}
简而言之,解决此问题的一种方法是,只要您希望相应地更新GUI,就可以使您的类实例看起来不同。
答案 3 :(得分:0)
问题可能是您使用GuiProductPartData
键入myProductPartData
返回ProductPartData
键入的ProductPartData
?但无论如何这不应该是这样的:)
将变量名称与类型相同并不是一个好习惯,因此您不应该拥有ProductPartData ProductPartData
属性。
答案 4 :(得分:0)
除了命名约定(假设只是输入错误)问题可能存在于ProductPartData类中。它是否也实现了INotifyPropertyChanged?