我有一个绑定到对象列表的列表框。对于每个列表项,我希望有一个矩形,其填充颜色由绑定对象的一些属性决定。所以我做了如下工作:
确保在我的对象上实现了inotifypropertychanged。
创建了一个类,将我感兴趣的属性公开为附加属性。
将对象的属性绑定到矩形的附加属性
创建了一个样式,该样式使用触发器根据附加属性设置矩形填充。
这是有效的,但仅在对象的属性第一次更改时有效。之后,当数据对象的属性更改时,附加的属性似乎没有收到通知。我已经进行了双重检查,我的数据对象正在引发inotifypropertychanged事件。有什么问题吗?
<Rectangle Style="{StaticResource RecordStateRectangleStyle}"
Width="10" Height="10" Stroke="Black"
local:RecordAttachment.RecordState="{Binding Path=RecordState}"
local:RecordAttachment.IsDeleted="{Binding Path=IsDeleted}" />
风格:
<Style x:Key="RecordStateRectangleStyle" TargetType="Rectangle">
<Style.Resources>
<SolidColorBrush x:Key="AddedStateBrush" Color="LightGreen" Opacity=".8" />
<SolidColorBrush x:Key="ModifiedStateBrush" Color="Orange" Opacity=".8" />
<SolidColorBrush x:Key="DeletedStateBrush" Color="Red" Opacity=".8" />
</Style.Resources>
<Style.Triggers>
<Trigger Property="local:RecordAttachment.RecordState" Value="{x:Static model:RecordState.Added}">
<Setter Property="Fill" Value="{StaticResource AddedStateBrush}" />
</Trigger>
<Trigger Property="local:RecordAttachment.RecordState" Value="{x:Static model:RecordState.Modified}">
<Setter Property="Fill" Value="{StaticResource ModifiedStateBrush}" />
</Trigger>
<Trigger Property="local:RecordAttachment.IsDeleted" Value="true">
<Setter Property="Fill" Value="{StaticResource DeletedStateBrush}" />
</Trigger>
</Style.Triggers>
</Style>
附加属性类:
Public Class RecordAttachment
Public Shared ReadOnly RecordStateProperty As DependencyProperty
Public Shared ReadOnly IsDeletedProperty As DependencyProperty
Shared Sub New()
RecordStateProperty = DependencyProperty.RegisterAttached("RecordState", _
GetType(Model.RecordState), _
GetType(RecordAttachment), _
New PropertyMetadata(Model.RecordState.Unchanged, AddressOf RecordStatePropertyChanged))
IsDeletedProperty = DependencyProperty.RegisterAttached("IsDeleted", _
GetType(Boolean), _
GetType(RecordAttachment), _
New PropertyMetadata(AddressOf DeletedPropertyChanged))
End Sub
Public Shared Sub SetRecordState(ByVal element As UIElement, ByVal state As Model.RecordState)
element.SetValue(RecordStateProperty, state)
End Sub
Public Shared Function GetRecordState(ByVal element As UIElement) As Model.RecordState
Return CType(element.GetValue(RecordStateProperty), Model.RecordState)
End Function
Public Shared Sub SetIsDeleted(ByVal element As UIElement, ByVal value As Boolean)
element.SetValue(IsDeletedProperty, value)
End Sub
Public Shared Function GetIsDeleted(ByVal element As UIElement) As Boolean
Return CType(element.GetValue(IsDeletedProperty), Boolean)
End Function
Public Shared Sub RecordStatePropertyChanged(ByVal sender As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
If sender IsNot Nothing Then
sender.SetValue(RecordStateProperty, e.NewValue)
End If
End Sub
Public Shared Sub DeletedPropertyChanged(ByVal sender As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
If sender IsNot Nothing Then
sender.SetValue(IsDeletedProperty, e.NewValue)
End If
End Sub
End Class
有人建议我发布C版,所以这里是:
public class RecordAttachment
{
public static readonly DependencyProperty RecordStateProperty;
public static readonly DependencyProperty IsDeletedProperty;
static RecordAttachment()
{
RecordStateProperty = DependencyProperty.RegisterAttached("RecordState",
typeof(model.RecordState),
typeof(RecordAttachment),
new PropertyMetadata(model.RecordState.Unchanged, RecordStatePropertyChanged));
IsDeletedProperty = DependencyProperty.RegisterAttached("IsDeleted",
typeof(bool),
typeof(RecordAttachment),
new PropertyMetadata(DeletedPropertyChanged));
}
public static void SetRecordState(UIElement element, model.RecordState state)
{
element.SetValue(RecordStateProperty, state);
}
public static model.RecordState GetRecordState(UIElement element)
{
return (model.RecordState)element.GetValue(RecordStateProperty);
}
public static void SetIsDeleted(UIElement element, bool value)
{
element.SetValue(IsDeletedProperty, value);
}
public static bool GetIsDeleted(UIElement element)
{
return (bool)element.GetValue(IsDeletedProperty);
}
public static void RecordStatePropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
if (sender != null)
sender.SetValue(RecordStateProperty, e.NewValue);
}
public static void DeletedPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
if (sender != null)
sender.SetValue(IsDeletedProperty, e.NewValue);
}
}
更新
我通过使用datatriggers而不是使用附加的属性和常规触发器解决了需要更改矩形填充颜色的根本问题。我仍然想知道为什么附加的属性“propertychanged”事件只触发一次。
我又做了一些谷歌搜索,发现了这个link的地方,josh smith说“一个附加的属性只能在一个元素上设置一次。”我环顾四周,找不到任何解释…
最佳答案
此问题是由属性更改处理程序中的以下代码行引起的:
sender.SetValue(RecordStateProperty, e.NewValue)
和
sender.SetValue(IsDeletedProperty, e.NewValue)
通过调用setValue,可以在目标上设置新的本地值。设置本地值将替换以前可能已存在的任何数据绑定。
简而言之,属性更改处理程序将删除该属性的数据绑定。
由于您正在有效地删除绑定,因此当数据源更改时,属性将不再更改,因为它不再是该属性的数据源。
属性更改通知就是-它告诉您属性的值正在更改。如果你不想的话,你不需要做任何回应,尤其是,你没有责任改变财产。反正会变的。