繁体   English   中英

将数据绑定到Silverlight ComboBox的IValueConverter

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM