2010-11-27 80 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) 

這將改變依賴的值,而不改變源

相關問題