WPF: поддержка времени разработки для свойств зависимостей со значениями по умолчанию - PullRequest
2 голосов
/ 13 октября 2019

Я написал пользовательский элемент управления на основе ListBox. Он содержит значение по умолчанию ItemTemplate, которое показывает изображение, присвоенное ListBox пользовательским свойством зависимости. Элемент управления также содержит изображение по умолчанию, которое используется, когда пользователь не передает изображение свойству зависимости.

Пока это работает, но теперь я обнаружил небольшую проблему и незнать, как это исправить.

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

Но когда я снова удаляю атрибут XAML для нового изображения, в конструкторе XAML отображается только белый прямоугольник. вместо изображения по умолчанию.

Я предполагаю, что это потому, что, установив свойство зависимости изображения на какое-то значение, а затем удалив его, я обнулил значение. Но даже когда я проверяю нулевое значение в CoerceCallback и возвращаю изображение по умолчанию, когда приведенное значение равно нулю, не работает.

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


TestControl.vb

Public Class TestControl
    Inherits ListBox

    Private Shared _defaultResources As ResourceDictionary

    Shared Sub New()
        _defaultResources = New ResourceDictionary
        _defaultResources.Source = New Uri("...")
    End Sub

    Public Shared ReadOnly TestProperty As DependencyProperty = DependencyProperty.Register(NameOf(TestControl.Test),
                                                                                            GetType(ImageSource),
                                                                                            GetType(TestControl),
                                                                                            New FrameworkPropertyMetadata(Nothing,
                                                                                                                          AddressOf TestControl.OnTestChanged,
                                                                                                                          AddressOf TestControl.OnTestCoerce))

    Public Property Test As ImageSource
        Get
            Return DirectCast(MyBase.GetValue(TestControl.TestProperty), ImageSource)
        End Get
        Set(value As ImageSource)
            MyBase.SetValue(TestControl.TestProperty, value)
        End Set
    End Property

    Private Shared Sub OnTestChanged(d As DependencyObject, e As DependencyPropertyChangedEventArgs)

    End Sub

    Private Shared Function OnTestCoerce(d As DependencyObject, value As Object) As Object
        If (value Is Nothing) Then
            Return TryCast(_defaultResources.Item("TestImage"), ImageSource)
        End If

        Return value
    End Function

    Public Sub New()
        Me.Test = TryCast(_defaultResources.Item("TestImage"), ImageSource)
    End Sub
End Class

Когда я использую этот элемент управления вот так

<local:TestControl ItemsSource="{Binding Items}" />

, каждый элемент показывает изображение по умолчанию во время разработки ,Когда я изменяю XAML на

<local:TestControl ItemsSource="{Binding Items}"
                   Test="{StaticResource NewImage}" />

, каждый элемент показывает новый элемент во время разработки . Но когда я снова удаляю Test="{StaticResource NewImage}", он не возвращается к образу по умолчанию.

1 Ответ

1 голос
/ 13 октября 2019

Хорошо, после некоторого тестирования (используя эту технику ) я обнаружил источник вашей проблемы.

Прежде всего, вы не используете PropertyMetadata для установки значения по умолчанию, новместо конструктора. Я предполагаю, что у вас есть веская причина для этого, но по сути это означает, что теперь вы полагаетесь на обратный вызов приведения для установки значения по умолчанию.

Однако оно не вызывается (фреймворк предполагает, что ваше "true""значение по умолчанию - Nothing - проверять не нужно) после удаления строки
Test="{StaticResource TestString}". Только OnTestChanged называется. Это означает, что мы можем использовать его для восстановления значения по умолчанию:

void OnTestChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
{
   if (e.NewValue is null)
   {
      ((TestControl)d).Test = yourDefaultImage;
      return;
   }

   //Actual "OnChanged" code
}

Действительно неуклюжее решение, но оно работает. В зависимости от вашей конкретной ситуации, вы также можете взглянуть на свойства Binding FallbackValue и TargetNullValue:
Test="{Binding Source={ }, FallbackValue={ }, TargetNullValue={ }}"

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