【问题标题】:Why do I have to declare a custom ValueConverter as a StaticResource and bind to the resource, instead of binding to its type?为什么我必须将自定义 ValueConverter 声明为 StaticResource 并绑定到资源,而不是绑定到其类型?
【发布时间】:2014-02-07 17:18:01
【问题描述】:

鉴于这个类:

namespace My.App.Converters
{
  [ValueConversion(typeof(bool?), typeof(Visibility))]
  public class NullableBooleanToVisibilityConverter : IValueConverter
  {
    ...
  }
}

为什么我必须执行以下操作:

<UserControl ...
             xmlns:converters="clr-namespace:My.App.Converters">
  <UserControl.Resources>
    <converters:NullableBooleanToVisibilityConverter x:Key="visibilityConverter" />
  </UserControl.Resources>
  ...
  <Button MinWidth="120" HorizontalAlignment="Left"
          Visibility="{Binding BackButtonVisible, Converter={StaticResource visibilityConverter}}" />
  ...
</UserControl>

而不是能够执行以下操作:

<UserControl ...
             xmlns:converters="clr-namespace:My.App.Converters">
  ...
  <Button MinWidth="120" HorizontalAlignment="Left"
          Visibility="{Binding BackButtonVisible, ConverterType={x:Type converters:NullableBooleanToVisibilityConverter}}" />
  ...
</UserControl>

假设我只想在我的应用程序的一个地方使用这个特定的转换器,即这个特定的UserControl

答案是否像“微软不想添加ConverterType,如果你真的想要,你可以自己用标记扩展来做”,或者这样做有没有好的编程风格的原因? ? (此示例不考虑“可重用性”。)

【问题讨论】:

    标签: c# wpf xaml


    【解决方案1】:

    问题是您没有获得转换器的实例。要解决同样的问题,只需将转换器的静态实例添加到 NullableBooleanToVisibilityConverter 类,如下所示

    namespace My.App.Converters
    {
      [ValueConversion(typeof(bool?), typeof(Visibility))]
      public class NullableBooleanToVisibilityConverter : IValueConverter
      {
        public static NullableBooleanToVisibilityConverter Instance = new NullableBooleanToVisibilityConverter();
    
       /* Convert and ConvertBack methods */
      }
    }
    

    编辑

    我忘了提到在绑定中你还必须访问静态实例

    <Button MinWidth="120" HorizontalAlignment="Left"
              Visibility="{Binding BackButtonVisible, Converter={x:Static:NullableBooleanToVisibilityConverter.Instance}}" />
    

    【讨论】:

    • 这对 OP 没有帮助,因为这个名为“Instance”的静态属性不会自动使用。您必须将“实例”分配给绑定,例如通过使用 {x:Static} 扩展。但这比使用 StaticResource 有什么好处吗? (支持非默认构造函数除外)
    • @eFloh 是的,我忘了说你我们需要在绑定中使用这个实例。请查看我更新的代码。还添加到您的问题 - 这个实例的好处是我们不必在每个页面中定义这个静态资源。
    【解决方案2】:
    ConverterType={x:Type converters:NullableBooleanToVisibilityConverter}
    

    这有你的转换器实例吗?尽管您的想法很好,但是通过提供类型绑定不会采用该转换器的实例..

    【讨论】:

      【解决方案3】:

      您不能只提供类型,因为您的转换器可能没有default parameterless constructor。因此,转换器的动态实例不能仅凭类型凭空变魔术。

      想要使用的成语引入了每次绑定更新时创建新转换的问题 - 从性能的角度来看,这是一种不好的做法。您可以通过缓存转​​换器来防止这种情况,但现在还有更多问题;

      • 什么时候应该刷新缓存(生成一个新的转换器)?
      • 什么时候应该释放缓存?
      • 如何更改转换器上的参数并确保它们在缓存刷新时不会丢失?

      【讨论】:

      • 你为什么认为没有 public ctor()?
      • @eFloh“可能没有有默认的无参数构造函数”。无法保证激活器会成功创建实例。这使得该模式远不如显式资源创建和相关好处有用。
      • 哦,对不起,我读错了“可能”。静态资源声明如何使用非默认 ctor?我假设您可以在代码中声明资源,但通常这不是我最喜欢的...
      • @eFloh stackoverflow.com/questions/1083159/… 在 .net 3.5 中,您必须单独设置属性。
      【解决方案4】:

      通过使用转换器的实例,您可以使用属性设置为特定值的转换器,请考虑以下(理论)示例:

      <UserControl ...
                   xmlns:converters="clr-namespace:My.App.Converters">
        <UserControl.Resources>
          <converters:NullableBooleanToVisibilityConverter x:Key="visibilityConverter"
                                                           IsInverted="True" />
        </UserControl.Resources>
        ...
        <Button MinWidth="120" HorizontalAlignment="Left"
                Visibility="{Binding BackButtonVisible, Converter={StaticResource visibilityConverter}}" />
        ...
      </UserControl>
      

      如果您绝对不想使用某个资源,您可以将实例声明为内联:

      <UserControl ...
                   xmlns:converters="clr-namespace:My.App.Converters">
        ...
        <Button MinWidth="120" HorizontalAlignment="Left"
                Visibility="{Binding BackButtonVisible, Converter={StaticResource visibilityConverter}}" />
          <Button.Visiblity>
            <Binding Path="BackButtonVisible">
              <Binding.Converter>
                <converters:NullableBooleanToVisibilityConverter x:Key="visibilityConverter" />
              </Binding.Converter>
            </Binding>
          </Button>
        ...
      </UserControl>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-10-16
        • 1970-01-01
        • 2017-02-24
        • 1970-01-01
        • 2017-10-04
        • 2011-06-22
        • 1970-01-01
        • 2011-01-31
        相关资源
        最近更新 更多