【问题标题】:ComboBox bound to a ObservableCollection does not update绑定到 ObservableCollection 的 ComboBox 不会更新
【发布时间】:2011-10-25 23:57:13
【问题描述】:

我有一个使用 ObservableCollection 作为源的 ComboBox。我的源绑定如下

<ComboBox IsEditable="False"
          SelectedIndex="{Binding Source={x:Static Properties:CollectionControl.Settings}, Path=SamplingPeriodIndex, Mode=TwoWay}"
          SelectionChanged="onPeriodControlSelectionChanged"
          Name="PeriodControl"
          ItemsSource="{StaticResource test}">
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding SamplingPeriod}" Visibility="{Binding Converter={StaticResource TrackVis}, ConverterParameter=GroupIndex}"/>
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>

TrackVis 是一个转换器,它根据实现了 INotifyPropertyChanged 的​​外部属性确定元素是可见还是折叠。

第一次显示 ComboBox 时,一切都按预期工作,但 ComboBox 永远不会刷新以反映更改。我一定是遗漏了什么,但到目前为止我所尝试的一切都失败了。

这是转换器的代码

public class IsVisibleConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, 
        System.Globalization.CultureInfo culture)
    {
        var tempObj = (SamplingPeriods) value;
        if (tempObj.GroupIndex >= CollectionControl.Settings.SamplingFrequencyIndex)
        {
            return Visibility.Visible;
        }

        return Visibility.Collapsed;
    }

    public object ConvertBack(object value, Type targetType, object parameter, 
        System.Globalization.CultureInfo culture)
    {
            throw new NotImplementedException();
    }
}

还有,这里是合集

public class PeriodsCollection : ObservableCollection<SamplingPeriods>
{
    public PeriodsCollection()
    {
        Add(new SamplingPeriods("1/16 of a second", 13));
        Add(new SamplingPeriods("1/8 of a second", 12));
        Add(new SamplingPeriods("1/4 of a second", 11));
        Add(new SamplingPeriods("1/2 of a second", 10));
        Add(new SamplingPeriods("1 second", 9));
        Add(new SamplingPeriods("2 seconds", 8));
        Add(new SamplingPeriods("4 seconds", 7));
        Add(new SamplingPeriods("8 seconds", 6));
        Add(new SamplingPeriods("16 seconds", 5));
        Add(new SamplingPeriods("32 seconds", 4));
        Add(new SamplingPeriods("64 seconds", 3));
        Add(new SamplingPeriods("128 seconds", 2));
        Add(new SamplingPeriods("256 seconds", 1));
        Add(new SamplingPeriods("512 seconds", 0));
    }
}

public class SamplingPeriods
{
    public SamplingPeriods(string samplingPeriod, int groupIndex)
    {
        SamplingPeriod = samplingPeriod;
        GroupIndex = groupIndex;
    }

    public string SamplingPeriod { get; private set; }
    public int GroupIndex { get; private set; }
}

这个想法是选定的采样频率限制了可用的采样周期。采样频率索引范围从 0 到 11。例如,如果采样索引为 9,则唯一有效的采样周期将具有 GroupIndex >= 9. 其他采样周期将被折叠。

【问题讨论】:

  • 为什么是静态资源而不是简单的属性名称?
  • 对 TrackVis 或 selectedindex 或两者的更改?
  • 在提出这样的问题时,具体说明未更新的内容非常重要。当您将新项目添加到集合中时,它们是否不会出现在 ComboBox 中?当您更改代码中的绑定属性时,SelectedIndex 是否不会更新?具体来说,发生了什么和没有发生什么?

标签: c# wpf xaml data-binding


【解决方案1】:

如果您的经期和频率都在同一个班级,为什么不也公开可用经期列表?然后,您可以使用 CollectionView 来过滤您的收藏,而不是转换器和可见性:

// initialize in your constructor
public PeriodsCollection AvailablePeriods { get; private set; }

public int SamplingFrequencyIndex
{
    get { return samplingFrequencyIndex; }
    set
    {
        samplingFrequencyIndex = value;
        RaisePropertyChanged("SamplingFrequencyIndex");
        var view = CollectionViewSource.GetDefaultView(AvailablePeriods) as ListCollectionView;
        view.Filter = o => ((SamplingPeriod)o).GroupIndex >= value;
    }
}

【讨论】:

    【解决方案2】:

    SamplingPeriods 需要实现 INotifyPropertyChanged 并且您需要在集合上调用 NotifyPropertyChanged。我会相信 CollectionControl.Settings.SamplingFrequencyIndex 持有您期望您从代码中获得的值,不清楚您在哪里设置它。当您更改 SamplingFrequencyIndex 时,您需要在 ObservabaleCollection 上调用 NotifyPropertyChanged 以强制刷新。必须有更好的方法来做到这一点。更改 SamplingPeriods 并传递对 SamplingFrequencyIndex 的引用,以便更改您要更改的实际对象。

       CollectionViewSource.GetDefaultView(lbFields.ItemsSource).Refresh();
    

    【讨论】:

    • 你让我和安倍一起思考,我决定采用不同的方法。我创建了一个 CollectionViewSource 和一个过滤器。然后,当触发 SamplingFrequencyIndex 事件时,我强制为 CollectionViewSource 执行 view.refresh。效果很好!感谢他们让我走上这条道路。
    【解决方案3】:

    您正在尝试跟踪采样频率指数。那么您必须绑定到具有此类属性并实现 INotifyPropertyChanged 的​​对象。或者,正如我已经说过的,将此事件传播到作为您的绑定源的对象,并在其上引发正确的 propertychanged。否则,绑定引擎将对该属性的更改一无所知。 使用Path = SamplingFrequencyIndex 绑定到CollectionControl.Settings

    【讨论】:

    • 当我添加 path = propertyWithChangeNotification 时,TrackVis 转换器永远不会被调用。
    • 带有更改通知的属性是指您的情况发生变化的属性。此属性是否驻留在“测试”对象中?
    • 在 VisualStudio 中转到视图>输出。调试应用时,输出中是否有任何绑定错误?
    • 1.该属性不在“测试对象”中 2. 没有绑定错误。
    • 你能用转换器的代码更新你的例子吗?现在我不明白你为什么要绑定到一个对象,而是试图反映另一个对象的属性变化。该代码将不起作用
    猜你喜欢
    • 1970-01-01
    • 2012-02-29
    • 2013-04-18
    • 2014-05-25
    • 2011-08-16
    • 2019-02-12
    • 2021-01-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多