我已经编写了一个基于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
}
确实是一个笨拙的解决方案,但它确实有效。根据您的具体情况,您可能还想查看 Binding
的 FallbackValue
和 TargetNullValue
属性:
Test="{Binding Source={ }, FallbackValue={ }, TargetNullValue={ }}"
关于WPF:设计时支持具有默认值的依赖属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58364475/