如何将ImageSource的TargetNullValue绑定到DependencyProperty

时间:2015-11-26 12:22:01

标签: wpf image xaml dependency-properties

我在自定义控件中有一个按钮,在Xaml中定义了一个像这样的图像(为了简洁起见,我刚刚添加了xaml中专门引用图像的部分;

<StackPanel>
                                <Image Style="{StaticResource vtlImageStyle}">
                                    <Image.Source>
                                        <Binding Path="FirstImage"
                                                 RelativeSource="{RelativeSource TemplatedParent}">
                                            <Binding.TargetNullValue>
                                                <ImageSource>/ViewToLearn.VtlWpfControls;component/Images/button_rounded_blue_previous24.png</ImageSource>
                                            </Binding.TargetNullValue>
                                        </Binding>
                                    </Image.Source>
                                </Image>
                            </StackPanel>

现在我想稍微改变一下,以便TargetNullValue实际上绑定到dependencyProperty,这样我就可以根据其他标准自由更改默认图像。

为此,我创建了一个string类型的依赖项属性来表示图像的Uri(具有自己的默认值)。

Protected Friend Shared ReadOnly DefaultFirstButtonImageUriProperty As DependencyProperty = DependencyProperty.Register("DefaultFirstButtonImageUri", GetType(String), GetType(VtlDataNavigator), New PropertyMetadata("/ViewToLearn.VtlWpfControls;component/Images/button_rounded_blue_first24.png", New PropertyChangedCallback(AddressOf OnDefaultFirstButtonImageUriChanged)))
Private Shared Sub OnDefaultFirstButtonImageUriChanged(ByVal o As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
    Dim vtlDataNavigator As VtlDataNavigator = CType(o, VtlDataNavigator)
    If vtlDataNavigator IsNot Nothing Then
        vtlDataNavigator.OnDefaultFirstButtonImageUriChanged(CType(e.OldValue, String), CType(e.NewValue, String))
    End If
End Sub

Protected Overridable Sub OnDefaultFirstButtonImageUriChanged(ByVal oldValue As String, ByVal newValue As String)
    ' TODO: Add your property changed side-effects. Descendants can override as well.
End Sub
Public Property DefaultFirstButtonImageUri As String
    ' IMPORTANT: To maintain parity between setting a property in XAML and procedural code, do not touch the getter and setter inside this dependency property!
    Get
        Return CType(GetValue(VtlDataNavigator.DefaultFirstButtonImageUriProperty), String)
    End Get
    Set(ByVal value As String)
        SetValue(VtlDataNavigator.DefaultFirstButtonImageUriProperty, value)
    End Set
End Property

然而,当我尝试在xaml中设置这样的时候

<Image.Source>
                                        <Binding Path="FirstImage"
                                                 RelativeSource="{RelativeSource TemplatedParent}">
                                            <Binding.TargetNullValue>
                                                <ImageSource>{Binding Path=DefaultFirstButtomImageUri}</ImageSource>
                                            </Binding.TargetNullValue>
                                        </Binding>
                                    </Image.Source>

它抛出一个错误,指出它无法从文本'{Binding Path = DefaultFirstButtonImageUri}'创建一个imagesource。很好,我理解这背后的逻辑,所以我尝试了另一种方法;

 <Image Style="{StaticResource vtlImageStyle}"
                                       Source="{Binding Path=FirstImage}"
                                       TargetNullValue="{Binding Path=DefaultFirstButtonImageUri}">
                                    <!--<Image.Source>
                                        <Binding Path="FirstImage"
                                                 RelativeSource="{RelativeSource TemplatedParent}">
                                            <Binding.TargetNullValue>
                                                <ImageSource>{Binding Path=DefaultFirstButtomImageUri}</ImageSource>
                                            </Binding.TargetNullValue>
                                        </Binding>
                                    </Image.Source>-->
                                </Image>

如果Image实际具有TargetNullValue属性,那将是一个非常简单的解决方案。

有人可以建议一种方法吗?

修改

为了回应使用PriorityBinding的建议(我之前从未遇到过,所以感谢有关的信息),我尝试了以下内容:

<Image Style="{StaticResource vtlImageStyle}">
                                    <Image.Source>
                                        <PriorityBinding>
                                            <Binding Path="FirstImage"></Binding>
                                            <Binding Path="DefaultFirstButtonImage"></Binding>
                                        </PriorityBinding>
                                    </Image.Source>
                                    <!--<Image.Source>
                                        <Binding Path="FirstImage"
                                                 RelativeSource="{RelativeSource TemplatedParent}">
                                            <Binding.TargetNullValue>
                                                <ImageSource>{Binding Path=DefaultFirstButtomImageUri}</ImageSource>
                                            </Binding.TargetNullValue>
                                        </Binding>
                                    </Image.Source>-->
                                </Image>

和DefaultFirstButtonImage dependecyProperty定义如下;

    Protected Friend Shared ReadOnly DefaultFirstButtonImageProperty As DependencyProperty = DependencyProperty.Register("DefaultFirstButtonImage", GetType(ImageSource), GetType(VtlDataNavigator), New PropertyMetadata(New BitmapImage(New Uri("/ViewToLearn.VtlWpfControls;component/Images/button_rounded_blue_first24.png")), New PropertyChangedCallback(AddressOf OnDefaultFirstButtonImageChanged)))

Private Shared Sub OnDefaultFirstButtonImageChanged(ByVal o As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
    Dim vtlDataNavigator As VtlDataNavigator = CType(o, VtlDataNavigator)
    If vtlDataNavigator IsNot Nothing Then
        vtlDataNavigator.OnDefaultFirstButtonImageChanged(CType(e.OldValue, ImageSource), CType(e.NewValue, ImageSource))
    End If
End Sub

Protected Friend Overridable Sub OnDefaultFirstButtonImageChanged(ByVal oldValue As ImageSource, ByVal newValue As ImageSource)
    ' TODO: Add your property changed side-effects. Descendants can override as well.
End Sub
Public Property DefaultFirstButtonImage As ImageSource
    ' IMPORTANT: To maintain parity between setting a property in XAML and procedural code, do not touch the getter and setter inside this dependency property!
    Get
        Return CType(GetValue(VtlDataNavigator.DefaultFirstButtonImageProperty), ImageSource)
    End Get
    Set(ByVal value As ImageSource)
        SetValue(VtlDataNavigator.DefaultFirstButtonImageProperty, value)
    End Set
End Property

不幸的是,这根本不起作用。当我放置一个我的控件实例,其中此代码驻留在窗口上时,我得到一个错误,指出无法确定Uri的格式。不幸的是,这是从我必须构建的测试应用程序抛出以测试控件,但是我怀疑它必须来自依赖属性。

0 个答案:

没有答案