Почему измененное свойство присоединенного свойства срабатывает только один раз? - PullRequest
4 голосов
/ 27 ноября 2010

У меня есть список, связанный со списком объектов.Для каждого элемента списка я хотел иметь прямоугольник, цвет заливки которого определяется несколькими свойствами связанного объекта.Поэтому я сделал следующее:

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

ОБНОВЛЕНИЕ Я решил свою основную проблему необходимости менять цвет прямоугольной заливки с помощью триггеров данных вместо использования прикрепленных свойств и регулярных триггеров.Я все еще хотел бы знать, почему событие присоединенного свойства 'propertyloaded' запускается только один раз.

Я немного погуглил и наткнулся на эту ссылку , где Джош Смит говорит: «Присоединенное свойство может быть установлено для элемента только один раз».Я оглянулся и не могу найти никакого объяснения ...

Ответы [ 2 ]

13 голосов
/ 28 ноября 2010

Проблема вызвана следующими строками кода в обработчиках изменения свойств:

sender.SetValue(RecordStateProperty, e.NewValue)

и

sender.SetValue(IsDeletedProperty, e.NewValue)

Вызывая SetValue, вы устанавливаете новое локальное значение для цели. Установка локального значения заменяет любую привязку данных, которая могла ранее существовать.

Короче говоря, ваш обработчик изменения свойства удаляет привязку данных для этого свойства.

Поскольку вы фактически удаляете привязку, ваше свойство больше не будет изменяться при изменении источника данных, поскольку оно больше не является источником данных для этого свойства.

Уведомление об изменении свойства - это просто сообщение о том, что значение свойства изменяется. Вам не нужно ничего предпринимать в ответ на это, если вы этого не хотите, и, в частности, вы не обязаны вносить изменения в собственность. Это все равно изменится.

2 голосов
/ 11 февраля 2017

В дополнение к выбранному ответу, это также может быть решено с помощью

Sender.SetCurrentValue(IsDeletedProperty, e.NewValue)

Это изменит значение зависимости без изменения источника

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...