【发布时间】:2012-03-10 22:02:58
【问题描述】:
我有一个允许用户选择每小时偏移量(0、3、6 或 9)的 ComboBox。但是,他们看到的内容需要显示为绝对时间,这是通过将偏移量添加到基本时间而得出的。例如如果基准时间是“0600”,用户可以选择“0600”、“0900”、“1200”和“1500”。
我正在使用 IValueConverter 将此偏移时间转换为绝对时间 通过将值绑定到转换器的自定义属性,将基本时间传递给转换器。 (代码见下文)。
现在这通常可以正常工作,除了 ComboBox 中最初选择的值的情况;这始终使用 UtcNow 的默认 BaseTime,并且不使用绑定值。通过在代码中设置断点,我可以看到 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 属性的绑定直到 为 UserControl 触发 Loaded 事件后才完成,因此当显示 ComboBox 时,而不是看到“0900 "(从 BaseTime 偏移 3 小时)作为当前值,我看到的内容更像是“17:47”,(从 UtcNow 偏移 3 小时)。当我单击 ComboBox 时,下拉列表中填充了正确的时间。由于事件的顺序,只是初始值错误。
调用OnLoaded,填充ComboBox,设置SelectedIndex,调用Convert,然后设置convert的BaseTime属性(为时已晚!)。
我怎样才能达到我需要的效果?我应该在其他事件上填充 ComboBox 吗?或者有没有更好的方法将基准时间传递给转换器?
【问题讨论】:
标签: c# silverlight data-binding combobox ivalueconverter