[英]Binding data to an IValueConverter for a Silverlight ComboBox
我有一个ComboBox,可让用户选择小时偏移量(0、3、6或9)。 但是,他们看到的内容需要显示为绝对时间,这是通过将偏移量与基本时间相加得出的。 例如,如果基准时间是“ 0600”,则用户可以从“ 0600”,“ 0900”,“ 1200”和“ 1500”中进行选择。
我正在使用IValueConverter将此偏移时间转换为绝对时间。通过将值绑定到转换器的自定义属性,将基准时间传递给转换器。 (请参见下面的代码)。
现在,除了ComboBox中最初选择的值的情况外,这通常可以正常工作; 这始终使用UtcNow的默认BaseTime,并且不使用绑定值。 通过在代码中设置断点,我可以看到直到调用Convert whch转换初始值之后,才设置BaseTime依赖项属性。
这是我正在使用的转换器类:
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;
}
}
问题在于,直到为UserControl触发Loaded事件之后 ,转换器的BaseTime属性的绑定才完成,因此显示ComboBox时,而不是当前看到“ 0900”(与BaseTime偏移3小时)值,我看到的更像是“ 17:47”(距离UtcNow 3小时偏移)。 当我单击组合框时,将在下拉列表中填充正确的时间。 由于事件的顺序,仅仅是初始值是错误的。
调用OnLoaded,填充ComboBox,设置SelectedIndex,调用Convert, 然后设置convert的BaseTime属性(太晚了!)。
如何达到所需的效果? 我是否应该在其他事件中填充ComboBox? 还是有更好的方法将基准时间传递给转换器?
这是一个古老的问题,但希望可以帮助任何人找到此页面。
将对象(在本例中为CurrentBaseTime)设置为视图模型的公共属性,并确保视图模型继承INotifyPropertyChanged。 加载值(在我的情况下,这是组合框的查找表),然后在加载后设置属性(引发属性更改)。
然后加载您的模型。 就我而言,我需要将三个值得元数据的查找表加载到viewmodel中,然后再加载模型。 然后,视图调用使用元数据(使用Dependency属性)预先填充的转换器。
ViewModel需要引发Property更改,否则转换器将陷入null,即上面的问题。
您需要通过绑定定义组合框的ItemsSource才能使Converter工作。
<ComboBox x:Name="forecastPeriodCombo" ItemsSource={Binding ObservableCollectionWithValues, Converter={StaticResource ForecastTimeConverter}} ... >
“ ObservableCollectionWithValues”是视图模型中的属性(如果使用mvvm)或代码背后的属性(这实际上是不正确的方法)。 如果不使用mvvm,则还要添加this.DataContext = this; 在控件的构造函数中。
关于转换器,我知道不可能对资源使用绑定(只能绑定到另一个静态资源)。 这意味着您的转换器将不会设置BaseTime属性。 尝试改用ConverterParameter将基本时间传递给转换器。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.