2010-11-27 82 views
4

我有一个绑定到对象列表的列表框。对于每个列表项,我想要一个矩形,其填充颜色由绑定对象的几个属性确定。所以我做了以下工作:为什么附属属性更改事件只发一次?

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

这工作,但只有第一次的对象更改的属性。之后,当数据对象的属性发生更改时,附加的属性似乎不会收到通知。我有双重检查,我的数据对象引发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); 
    } 
} 

UPDATE 我解决了需要使用datatriggers而不是使用附加属性和定期触发改变矩形填充颜色的我根本问题。我仍然想知道为什么附加属性'属性changed'事件只被解雇一次。

我做了一些更多的搜索,我碰到了这个link,Josh Smith说'一个附属属性只能在元素上设置一次。'。我环顾四周,我无法找到任何解释...

+0

@Cooper解决 - XAML中似乎是罚款,但让我给你一个建议;如果你可以用C#发布你的代码,那将是非常好的!我觉得你会得到更多的答案,我也可以帮助你!我在VB非常糟糕!我试图使用在线工具将您的代码转换为C#,但它给了我一些错误,比如'sub not found'等,我不知道VB!这将是非常好的,如果你可以将你的代码转换为C#并将它与你的VB代码一起发布在这里:) – GuruC 2010-11-27 20:05:18

回答

13

问题是由这些代码行中的物性变化引起的处理程序:

sender.SetValue(RecordStateProperty, e.NewValue) 

sender.SetValue(IsDeletedProperty, e.NewValue) 

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

总之,你的属性更改处理程序删除数据为该属性的绑定。

既然你有效去除结合,你的财产将不再改变时,数据源的变化,因为它不再是该属性的数据源。

的属性更改通知就是这样 - 它会告诉你该属性的值发生变化。如果你不想做任何事情,你不需要做任何事情,特别是,改变财产不是你的责任。无论如何,它将会改变。

2

除了选定的答案,这也可以通过使用

Sender.SetCurrentValue(IsDeletedProperty, e.NewValue) 

这将改变依赖的值,而不改变源

相关问题