【问题标题】:Use IValueConverter with DynamicResource?将 IValueConverter 与 DynamicResource 一起使用?
【发布时间】:2011-06-15 21:01:38
【问题描述】:

在使用DynamicResource 扩展时,有没有办法定义转换器?

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

不幸的是,这给了我以下异常:

“DynamicResourceExtension”不能 在类型的“源”属性上设置 '捆绑'。一种 'DynamicResourceExtension' 只能是 在 a 的 DependencyProperty 上设置 依赖对象。

【问题讨论】:

    标签: wpf binding ivalueconverter dynamicresource


    【解决方案1】:

    我知道我真的迟到了,但绝对有效的是使用 BindingProxy 像这样的 DynamicResource

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

    然后将转换器应用到代理

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

    【讨论】:

    • 这是一个很棒的发现!您还可以使用它来访问文章中描述的 DataContext 。已经添加到我们的工具集中! :)
    • 我是最初投票赞成这个答案的人之一,但实际上我只是想出了一个更简单的解决方案,它基于类似的“代理”概念,除了代理是自动处理的并且透明地在 MarkupExtension 后面。查看我关于这个主题的帖子...stackoverflow.com/questions/33816511/…
    • 我喜欢这样!请注意,除非将标记扩展移动到单独的项目/程序集中,否则 XAML 可能很难发现标记扩展。
    • 我发现标记扩展的可发现性取决于 XML 命名空间的定义方式:xmlns:my="clr-namespace:MyNamespace1.MyNamespace2" 编译并找到标记扩展,而 xmlns:my="clr-namespace:MyNamespace1.MyNamespace2;assembly=MyAssembly" 没有。
    【解决方案2】:

    试试这样的:

    标记扩展:

    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}}" />
    

    【讨论】:

    • 我收到以下编译器错误:Unknown property 'Converter' for type 'MS.Internal.Markup.MarkupExtensionParser+UnknownMarkupExtension'
    • 好主意,但它不起作用。不匹配:ProvideValue 由 XAML 解析器调用一次,不应转换任何内容。相反,它应该为依赖属性提供一些启用转换的东西。
    • 考虑到他在引用您的文章,您为什么不使用@mkoertgen 方法?有什么缺点吗?
    • @Dzyann,因为我在发布这个答案时还没有写这篇文章;)
    • 哈哈!我完全看错了日期。但很高兴知道您没有看到其他方法的缺点。谢谢!
    【解决方案3】:

    @Thomas 的帖子非常接近,但正如其他人指出的那样,它仅在执行 MarkupExtension 时执行。

    这是一个真正绑定的解决方案,不需要“代理”对象,并且编写起来就像任何其他绑定一样,除了源和路径,你给它一个资源键......

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

    【讨论】:

      【解决方案4】:

      我喜欢 mkoertgen 的回答。

      这是一个适用于我的 VB.NET 中 IValueConverter 代理的改编示例。我的资源“VisibilityConverter”现在包含为 DynamicResource 并与 ConverterProxy“VisibilityConverterProxy”一起转发。

      用法:

      ...
      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}}"
      

      代码:

      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
      

      结束命名空间

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-07-02
        • 1970-01-01
        • 2013-12-30
        • 2011-05-23
        • 2015-09-21
        • 2014-08-08
        • 2023-03-22
        • 1970-01-01
        相关资源
        最近更新 更多