为什么附加属性属性更改事件只触发一次? [英] Why is attached property property changed event only firing one time?

查看:24
本文介绍了为什么附加属性属性更改事件只触发一次?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个绑定到对象列表的列表框.对于每个列表项,我想要一个矩形,其填充颜色由绑定对象的一些属性决定.所以我做了以下事情:

I have a listbox binded to a list of objects. For each list item I wanted to have a rectangle whose fill color is determined by a few properties of the binded object. So I did the following:

  1. 确保在我的对象上实现了 INotifyPropertyChanged.
  2. 创建了一个类来公开我感兴趣的属性作为附加属性.
  3. 将对象的属性绑定到矩形的附加属性
  4. 创建了一种样式,该样式使用触发器根据附加属性设置矩形填充.

这有效,但仅在对象的属性第一次更改时.之后,当数据对象的属性更改时,附加属性似乎没有收到通知.我已经仔细检查过,我的数据对象正在引发 INotifyPropertyChanged 事件.可能是什么问题?

This works, but only the first time the property of the object changes. After that, the attached properties do not seem to be receiving notification when the data object's property changes. I have double checked and my data object is raising the INotifyPropertyChanged event. What could be the problem?

<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# 版本,所以这里是:

Someone suggested I post C# version, so here it is:

    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);
    }
}

更新我通过使用数据触发器而不是使用附加属性和常规触发器解决了需要更改矩形填充颜色的潜在问题.我仍然想知道为什么附加属性 'propertychanged' 事件只触发一次.

UPDATE I solved my underlying problem of needing to change the color of the rectangle fill by using datatriggers instead of using the attached properties and regular triggers. I would still like to know why the attached property 'propertychanged' event is only fired once though.

我做了更多的谷歌搜索,我发现了这个 link 乔什史密斯说'附加属性只能在一个元素上设置一次.'.我环顾四周,找不到任何解释...

I did some more googling and I came across this link where Josh Smith says 'An attached property can only be set on an element once.'. I've looked around and I can't find any explanation...

推荐答案

问题是由属性更改处理程序中的这些代码行引起的:

The problem is caused by these lines of code in the property change handlers:

sender.SetValue(RecordStateProperty, e.NewValue)

sender.SetValue(IsDeletedProperty, e.NewValue)

通过调用 SetValue,您可以在目标上设置新的本地值.设置本地值会替换之前可能存在的任何数据绑定.

By calling SetValue, you are setting a new local value on the target. Setting a local value replaces any data binding that might previously have been in place.

简而言之,您的属性更改处理程序会删除该属性的数据绑定.

In short, your property change handler removes the data binding for that property.

由于您有效地移除了绑定,因此当数据源更改时,您的属性将不再更改,因为它不再是该属性的数据源.

Since you are effectively removing the binding, your property will no longer change when the data source changes because it is no longer the data source for that property.

属性更改通知就是这样 - 它告诉您属性的值正在更改.如果您不想,您无需对此做出任何回应,特别是,您没有责任更改属性.无论如何它都会改变.

A property change notification is just that - it tells you that the property's value is changing. You do not need to do anything in response to that if you don't want to, and in particular, it's not your responsibility to make the property change. It's going to change anyway.

这篇关于为什么附加属性属性更改事件只触发一次?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆