Use IValueConverter with DynamicResource?

こ雲淡風輕ζ 提交于 2019-11-26 20:16:57

问题


Is there a way to define a converter when using the DynamicResource extension? Something in the lines of

<RowDefinition Height="{Binding Source={DynamicResource someHeight}, Converter={StaticResource gridLengthConverter}}" />

which unfortunately gives me the following excpetion:

A 'DynamicResourceExtension' cannot be set on the 'Source' property of type 'Binding'. A 'DynamicResourceExtension' can only be set on a DependencyProperty of a DependencyObject.


回答1:


I know i am really late to this but what definitely works is using a BindingProxy for the DynamicResource like this

<my:BindingProxy x:Key="someHeightProxy" Data="{DynamicResource someHeight}" />

Then applying the converter to the proxy

<RowDefinition Height="{Binding Source={StaticResource someHeightProxy}, Path=Data, Converter={StaticResource gridLengthConverter}}" />



回答2:


Try something like that:

Markup extension:

public class DynamicResourceWithConverterExtension : DynamicResourceExtension
{
    public DynamicResourceWithConverterExtension()
    {
    }

    public DynamicResourceWithConverterExtension(object resourceKey)
            : base(resourceKey)
    {
    }

    public IValueConverter Converter { get; set; }
    public object ConverterParameter { get; set; }

    public override object ProvideValue(IServiceProvider provider)
    {
        object value = base.ProvideValue(provider);
        if (value != this && Converter != null)
        {
            Type targetType = null;
            var target = (IProvideValueTarget)provider.GetService(typeof(IProvideValueTarget));
            if (target != null)
            {
                DependencyProperty targetDp = target.TargetProperty as DependencyProperty;
                if (targetDp != null)
                {
                    targetType = targetDp.PropertyType;
                }
            }
            if (targetType != null)
                return Converter.Convert(value, targetType, ConverterParameter, CultureInfo.CurrentCulture);
        }

        return value;
    }
}

XAML:

<RowDefinition Height="{my:DynamicResourceWithConverter someHeight, Converter={StaticResource gridLengthConverter}}" />



回答3:


@Thomas's post is very close, but as others have pointed out, it only executes at the time the MarkupExtension is executed.

Here's a solution that does true binding, doesn't require 'proxy' objects, and is written just like any other binding, except instead of a source and path, you give it a resource key...

How do you create a DynamicResourceBinding that supports Converters, StringFormat?




回答4:


I like the answer of mkoertgen.

Here is an adapted example for a IValueConverter proxy in VB.NET that worked for me. My resource "VisibilityConverter" is now included as DynamicResource and forwarded with the ConverterProxy "VisibilityConverterProxy".

Usage:

...
xmlns:binding="clr-namespace:Common.Utilities.ModelViewViewModelInfrastructure.Binding;assembly=Common"
...
<ResourceDictionary>
    <binding:ConverterProxy x:Key="VisibilityConverterProxy" Data="{DynamicResource VisibilityConverter}" />
</ResourceDictionary>
...
Visibility="{Binding IsReadOnly, Converter={StaticResource VisibilityConverterProxy}}"

Code:

Imports System.Globalization

Namespace Utilities.ModelViewViewModelInfrastructure.Binding

''' <summary>
''' The ConverterProxy can be used to replace StaticResources with DynamicResources.
''' The replacement helps to test the xaml classes. See ToolView.xaml for an example
''' how to use this class.
''' </summary>
Public Class ConverterProxy
    Inherits Freezable
    Implements IValueConverter

#Region "ATTRIBUTES"

    'Using a DependencyProperty as the backing store for Data.  This enables animation, styling, binding, etc...
    Public Shared ReadOnly DataProperty As DependencyProperty =
                                DependencyProperty.Register("Data", GetType(IValueConverter), GetType(ConverterProxy), New UIPropertyMetadata(Nothing))

    ''' <summary>
    ''' The IValueConverter the proxy redirects to
    ''' </summary>
    Public Property Data As IValueConverter
        Get
            Return CType(GetValue(DataProperty), IValueConverter)
        End Get
        Set(value As IValueConverter)
            SetValue(DataProperty, value)
        End Set
    End Property

#End Region


#Region "METHODS"

    Protected Overrides Function CreateInstanceCore() As Freezable
        Return New ConverterProxy()
    End Function

    Public Function Convert(ByVal value As Object, ByVal targetType As Type, ByVal parameter As Object, ByVal culture As CultureInfo) As Object Implements IValueConverter.Convert
        Return Data.Convert(value, targetType, parameter, culture)
    End Function

    Public Function ConvertBack(ByVal value As Object, ByVal targetType As Type, ByVal parameter As Object, ByVal culture As CultureInfo) As Object Implements IValueConverter.ConvertBack
        Return Data.ConvertBack(value, targetType, parameter, culture)
    End Function

#End Region



End Class

End Namespace



来源:https://stackoverflow.com/questions/4805351/use-ivalueconverter-with-dynamicresource

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!