如何使用MultiValueConverter防止Multibinding多次获取值并使用适当的参数

时间:2015-01-29 14:10:36

标签: wpf multibinding imultivalueconverter

我想显示有关指定时间刻度的时间信息(例如小时,分钟,秒)。此信息显示在列表框的项目中。为此,我为ListBoxItem创建了一个自定义ControlTemplate,如:

<ControlTemplate TargetType="ListBoxItem">                      
   <Controls:ExtendedTextBlock x:Name="time" d:LayoutOverrides="Width">
     <Controls:ExtendedTextBlock.Text>
       <MultiBinding Converter="{StaticResource scaledDateToStringConverter}" FallbackValue="">
          <Binding Path="Time"></Binding>
          <Binding Path="TimelineScale"></Binding>
      </MultiBinding>                       
</ControlTemplate>

转换器执行以下操作:

public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        var scale = (TimelineScale)values[1];
        var timestamp = (DateTime)values[0];
        string convertedTimestamp;

        if (timestamp == default(DateTime))
        {
            convertedTimestamp = "LIVE";
        }
        else
        {
            switch (scale)
            {
                case TimelineScale.Seconds:
                    convertedTimestamp = timestamp.ToString("T", CultureInfo.CurrentCulture);
                    break;
                case TimelineScale.Minutes:
                    convertedTimestamp = timestamp.ToString("t", CultureInfo.CurrentCulture);
                    break;
                case TimelineScale.Hours:
                    convertedTimestamp = timestamp.AddMinutes(-timestamp.Minute).AddSeconds(-timestamp.Second).ToString("t", CultureInfo.CurrentCulture);
                    break;
                default:
                    convertedTimestamp = timestamp.ToString("T", CultureInfo.CurrentCulture);
                    break;
            }
        }

        return convertedTimestamp;
    }

问题是对于某些项目,多次调用Convert方法并且在第一次调用时,而不是实际时间值-DependencyProperty.UnsetValue作为参数传递,在从输入数组中取消装箱值时导致InvalidCastException。如何只使用有效参数一次和(至少)实现转换?

关于这个问题有一些有趣的评论: 时间的价值是明确定义的。 这个代码工作了很长时间,因为.NET ver。 4.0但问题现在才出现(至少它开始不断地由客户和我们的测试机器重现)

1 个答案:

答案 0 :(得分:1)

转换器很可能正在评估每个绑定属性的设置。因此,无论先设置哪个属性(TimeTimelineScale),MultiBinding都会进行评估,而另一个属性将具有未设置的值,因为它尚未进行评估。

有几种方法可以解决这个问题。

返回 UnsetValue

将以下内容添加到Convert方法的顶部:

if (!(values[1] is TimelineScale) || !(values[0] is DateTime))
{
    return DependencyProperty.UnsetValue;
}

使用默认值

var scale = (values[1] as TimelineScale?).GetValueOrDefault();
var timestamp = (values[0] as DateTime?).GetValueOrDefault();

在任何一种情况下,一旦绑定第二次评估,Convert将具有所需的参数,并且MultiBinding将正确更新。

编辑:您的上游绑定可能不正确。我有一个同事最近遇到了一个问题,UnsetValue出现在一个带有绑定的值上,其中绑定路径拼写错误。这可能是.NET / WPF 4.0中引入的一种新行为。