2015-01-29 5 views
0

Я хочу отображать информацию о времени относительно заданного временного масштаба (например, часов, минут, секунд). Эта информация отображается в элементах списка. Чтобы сделать это, я создал пользовательский ControlTemplate для ListBoxItem-s как:Как предотвратить Multibinding с MultiValueConverter от получения значения несколько раз и с соответствующими параметрами

<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; 
    } 

Проблема в том, что для некоторых элементов Преобразовать метод вызывается более одного раза и при первом вызове вместо фактического значения времени -DependencyProperty.UnsetValue передается как параметр, вызывая InvalidCastException при распаковке значения из входного массива. Как я могу достичь преобразования только один раз и (по крайней мере) с действительными параметрами?

Есть несколько интересных замечаний по этой проблеме: Значение времени определено с неопределенным сроком. Этот код работает в течение длительного времени, так как .NET ver. 4.0, но проблема появилась только сейчас (по крайней мере, она начала постоянно воспроизводить клиенты и наши тестовые машины)

ответ

1

Скорее всего, конвертер оценивается по мере установки каждого из связанных свойств. Поэтому в зависимости от того, какое свойство (Time или TimelineScale) установлено первым, значение MultiBinding оценивается, а другое будет иметь значение unset, так как оно еще не было оценено.

Есть несколько способов справиться с этим.

Вернуться 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(); 

В любом случае, как только привязка eva luates во второй раз, Convert будет иметь необходимые параметры, и ваш MultiBinding будет корректно обновляться.

Редактировать: Возможно, что у вас неверная привязка вверх. У меня есть сотрудник, который недавно столкнулся с проблемой с UnsetValue, появляющейся на значении с привязкой, где путь привязки был орфографическим. Возможно, это новое поведение, введенное в .NET/WPF 4.0.

+0

Я знаю об этом подходе, но просто хочу избежать выполнения дополнительных строк кода. Коллекция довольно большая, и приложение в целом тяжелое. Я бы предпочел выяснить, почему это происходит для нескольких элементов в списке и как его предотвратить. – vklu4itesvet

+0

Я не думаю, что вы можете предотвратить это. Возврат UnsetValue будет более результативным, чем исключение. – NextInLine

+0

Вы также можете использовать '' для каждой из привязок - это, вероятно, заменит 'DependencyProperty.UnsetValue' значение, которое может обрабатывать ваш конвертер. – NextInLine