【问题标题】:Markup extensions and object creation标记扩展和对象创建
【发布时间】:2013-01-22 12:31:38
【问题描述】:

目前我有这样的标记

<TextBlock>
  <TextBlock.Text>
    <Binding Path="Value" ElementName="window" ConverterParameter="M">
      <Binding.Converter>
        <local:DatePartValueConverter />
      </Binding.Converter>
     </Binding>
  </TextBlock.Text>
</TextBlock>

我想把它缩短成这样

<TextBlock Text="{Binding Path=Value,ElementName=window,
  ConverterParameter=M,Converter={local:DatePartValueConverter}}" />

但是编译器会出错,因为 DatePartValueConverter 不是从 MarkupExtension 派生的。没有其他方法可以获取短格式标记来创建 DatePartValueConverter 的实例吗?

顺便说一句,我尝试从 MarkupExtension 派生,它确实解决了问题。我的 ProvideValue 实现如下所示

public override object ProvideValue(IServiceProvider serviceProvider)
{
  return new DatePartValueConverter();
}

它确实有效,但我仍然不清楚serviceProvider 的起源和性质以及人们可能会用它做什么。

有趣的是,当我在使用此标记扩展的绑定上使用 Visual Studio 2012 绑定编辑器时,它立即再次扩展它,使得整个标记扩展支持变得毫无意义。

我可能应该提到,我需要为每个绑定提供一个私有实例,因为它维护内部状态 - 它需要知道整个 DateTime 值来设置某些方面,就像这样

public object ConvertBack(object value, Type targetType, 
  object parameter, System.Globalization.CultureInfo culture)
{
  culture = System.Globalization.CultureInfo.CurrentCulture;
  var strValue = value as string;
  int y = _value.Year, M = _value.Month, d = _value.Day,
    H = _value.Hour, m = _value.Minute, s = _value.Second;
  if (strValue == null)
    return null;
  else
  {
    string p = parameter as string;
    switch (p)
    {
      case "yyyy":
        y = int.Parse(strValue); break;
      case "yy":
        y = (strValue.Length == 4) ?
          int.Parse(strValue) :
          int.Parse(DateTime.Now.Year.ToString().Substring(0, 2) + strValue);
        break;
      case "M":
      case "MM":
        M = int.Parse(strValue); break;
      ...
    }
  }
  return new DateTime(y, M, d, H, m, s);
}

【问题讨论】:

    标签: c# wpf markup-extensions


    【解决方案1】:

    您可以创建DatePartValueConverter 的实例作为资源,然后使用它。

    <Window.Resources>
      <local:DatePartValueConverter x:Key="datePartValueConverter" />
    </Window.Resources>
    
    <TextBlock Text="{Binding Path=Value, ElementName=window,
      ConverterParameter=M, Converter={StaticResource datePartValueConverter}}" />
    

    编辑如果您确实想让转换器成为MarkupExtension,那么您可以这样做。您可以在ProvideValue 中返回一个新实例,也可以在return this; 中返回当前实例

    通过返回当前实例,您可以在转换器中拥有属性,并允许您执行此类操作。

    public class DatePartValueConverter : MarkupExtension, IValueConverter {
        public string ParseType { get; set; }
        // other methods
    }
    
    <TextBlock Text="{Binding Path=Value, ElementName=window,
      Converter={local:DatePartValueConverter ParseType=M}}" />
    

    至于IServiceProviderMarkupExtension.ProvideValue — Is the IServiceProvider actually used?

    【讨论】:

    • 注意 StaticResource 不能满足每个绑定对实例的需求。但是 MarkupExtension 的东西很有用,而且 IServiceProvider 链接是黄金。
    【解决方案2】:

    据我所知,除了从MarkupExtension 派生转换器之外的唯一方法是创建自己的自定义绑定类(查看DelayBinding)。

    【讨论】:

    • 你证实了我下沉的感觉。我放弃并使用完整的符号而不是标记扩展。
    猜你喜欢
    • 2012-04-04
    • 2013-06-17
    • 2018-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多