0

我想显示有关指定时间尺度(例如小时、分钟、秒)的时间信息。此信息显示在列表框的项目中。为此,我为 ListBoxItem-s 创建了一个自定义 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 版本以来,此代码已经运行了很长时间。4.0 但问题现在才出现(至少它开始不断地被客户和我们的测试机器复制)

4

1 回答 1

1

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

有几种方法可以处理这个问题。

返回未设置值

将以下内容添加到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 中引入的一种新行为。

于 2015-01-29T16:46:33.463 回答