WPF:设计时支持具有默认值的依赖属性

标签 wpf vb.net design-time

我已经编写了一个基于ListBox 的自定义控件。它包含一个默认的 ItemTemplate,它显示由自定义依赖属性提供给 ListBox 的图像。该控件还包含一个默认图像,当用户未向依赖属性提供图像时使用该图像。

到目前为止,这是有效的,但现在我发现了一个小问题,我不知道如何解决。

当我在 XAML 设计器中使用我的自定义控件时,它首先显示默认图像。当我将图像的依赖属性设置为另一个图像时,新图像立即显示在 XAML 设计器中。

但是当我再次删除新图像的 XAML 属性时,XAML 设计器只显示一个白色矩形而不是默认图像。

我假设这是因为将图像的依赖属性设置为某个值然后将其删除我使该值无效。但即使我在 CoerceCallback 中检查 null 并在强制值为 null 时返回默认图像,也不起作用。

支持依赖属性回退值的最佳方式是什么?


测试控件.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}" 时,它不会返回到默认图像。

最佳答案

好的,经过一些测试(使用 this technique )我发现了问题的根源。

首先,您没有使用 PropertyMetadata 来设置默认值,而是使用构造函数。我假设您有充分的理由这样做,但这实际上意味着您现在依赖强制回调来设置默认值。

但是,在您删除
Test="{StaticResource TestString}" 行。只有 OnTestChanged 叫做。这意味着我们可以使用它来恢复默认值:

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

   //Actual "OnChanged" code
}

确实是一个笨拙的解决方案,但它确实有效。根据您的具体情况,您可能还想查看 BindingFallbackValueTargetNullValue 属性:
Test="{Binding Source={ }, FallbackValue={ }, TargetNullValue={ }}"

关于WPF:设计时支持具有默认值的依赖属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58364475/

相关文章:

用于列表框和列表项的 WPF 嵌套数据绑定(bind)

wpf - 我可以阻止 WPF 中窗口的最大化吗?

.net - 获取网页内容并进行处理(打印或保存到文件)

c# - .NET Windows 窗体问题的自定义设计器类

delphi - 如何在delphi设计时在我的自定义控件中选择子控件

WPF XAML 网格可见性触发器

wpf - 从 UI 绑定(bind)到 View 模型属性需要从 TextBox 中移除焦点

c# - 如何将用户提供的输入添加到 SQL 语句?

vb.net - 如何从字体文件名获取字体属性?

c# - 隐藏可扩展属性的省略号 (…) 按钮,例如属性网格中字体属性的 "…"按钮