У меня есть ComboBox, который позволяет пользователю выбирать часовое смещение (0, 3, 6 или 9). Однако то, что они видят, нужно показывать как абсолютное время, которое получается путем добавления смещения к базовому времени. например если базовое время равно «0600», пользователь может выбрать «0600», «0900», «1200» и «1500».
Я использую IValueConverter для преобразования этого времени смещения в абсолютное время. Базовое время передается преобразователю путем привязки значения к пользовательскому свойству преобразователя. (см. код ниже).
Теперь это обычно работает нормально, за исключением случая изначально выбранного значения в ComboBox; это всегда использует BaseTime по умолчанию UtcNow и не использует связанное значение. Устанавливая точки останова в коде, я вижу, что свойство зависимости BaseTime не устанавливается до тех пор, пока после вызова Convert не произойдет преобразование начального значения.
Это класс конвертера, который я использую:
public class ForecastTimeConverter : DependencyObject, IValueConverter
{
// Register the dependency property we need for the BaseTime property.
public DependencyProperty BaseTimeProperty = DependencyProperty.Register(
"BaseTime",
typeof(DateTime),
typeof(ForecastTimeConverter),
new PropertyMetadata(DateTime.UtcNow, BaseTimeChanged)
);
private static void BaseTimeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
// this method here just so I can set a breakpoint to see when the property is set.
}
public DateTime BaseTime
{
get { return (DateTime)GetValue(BaseTimeProperty);}
set { SetValue(BaseTimeProperty, value); }
}
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
string forecast_time;
if (value is string)
{
try
{
// get forecast period, in hours.
int hours = System.Convert.ToInt32(value as string);
// add forecast period to base time to get final forecast time.
DateTime forecastTime = BaseTime + new TimeSpan(hours, 0, 0);
forecast_time = String.Format("{0:HHmm}z", forecastTime);
}
catch
{
forecast_time = "?";
}
}
else
{
throw new NotImplementedException("Can't convert from type '" + typeof(ValueType) + "'");
}
return forecast_time;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
Полный исходный код XAML и UserControl довольно большой, поэтому здесь приведены только соответствующие биты:
<UserControl.Resources>
<status:ForecastTimeConverter x:Key="ForecastTimeConverter" BaseTime="{Binding Path=CurrentBaseTime}" />
</UserControl.Resources>
...
<ComboBox x:Name="forecastPeriodCombo" Grid.Row="0" Grid.Column="1" Width="100" SelectionChanged="OnforecastPeriodChanged" >
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Converter={StaticResource ForecastTimeConverter}}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
И соответствующий код, стоящий за XAML, упрощен:
public partial class MyControl : UserControl
{
public MyControl()
{
InitializeComponent();
this.Loaded += OnLoaded;
}
public void OnLoaded(object sender, EventArgs e)
{
forecastPeriodCombo.Items.Clear();
List<string> values = new List<string>();
values.Add("0");
values.Add("3");
values.Add("6");
values.Add("9");
forecastPeriodCombo.ItemsSource = values;
forecastPeriodCombo.SelectedIndex = 1;
}
}
Проблема заключается в том, что привязка свойства BaseTime конвертера не выполняется до тех пор, пока после не сработает событие Loaded для UserControl, поэтому вместо отображения «0900» отображается ComboBox (Смещение на 3 часа от BaseTime) в качестве текущего значения, я вижу что-то вроде «17:47», (смещение на 3 часа от UtcNow). Когда я нажимаю на ComboBox, в раскрывающемся списке указывается правильное время. Это просто начальное значение, которое неверно из-за порядка событий.
OnLoaded вызывается, ComboBox заполняется, SelectedIndex установлен, Convert вызывается, затем свойство BaseTime преобразования установлено (слишком поздно!).
Как мне добиться нужного эффекта? Должен ли я заполнить ComboBox на каком-то другом событии? Или, может быть, есть лучший способ передать базовое время конвертеру?