我想显示有关指定时间刻度的时间信息(例如小时,分钟,秒)。此信息显示在列表框的项目中。为此,我为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但问题现在才出现(至少它开始不断地由客户和我们的测试机器重现)
答案 0 :(得分:1)
转换器很可能正在评估每个绑定属性的设置。因此,无论先设置哪个属性(Time
或TimelineScale
),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中引入的一种新行为。