ComboBox bound to a ObservableCollection does not update
I have a ComboBox that uses a ObservableCollection as the source. I have the source bound as follows
<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 is a converter that determines if the elem开发者_如何学编程ent is visible or collapsed depending on an external property which has INotifyPropertyChanged implemented.
Everything works as expected the first time the ComboBox is displayed, but the ComboBox is never refreshed to reflect changes. I must be missing something, but as of now everything I have tried fails.
Here is the code for the converter
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();
}
}
Also, here is the collection
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; }
}
The idea is that the selected sampling frequency limits the sampling periods that are available. The sampling frequency index ranges from 0 to 11. For example, if the sampling index is 9 the only valid sampling periods would have a GroupIndex >= 9. The other sampling periods would be collapsed.
You are trying to track samplingfrequency index. then you must bind to an object that have such property and implements INotifyPropertyChanged.Or, as I have already said, propagate this event to the object that is your binding source, and raise correct propertychanged on it. Otherwise, binding engine would know nothing of the changes of that property.
Bind to the CollectionControl.Settings
with a Path = SamplingFrequencyIndex
SamplingPeriods needs to implement INotifyPropertyChanged and you need to call NotifyPropertyChanged on the set. I will take it on faith at CollectionControl.Settings.SamplingFrequencyIndex holds the value you expect you from you code it is not clear where you set that. When you change SamplingFrequencyIndex you need to call NotifyPropertyChanged on ObservabaleCollection of possible force a refresh. There has got to be a better way to do this. Change SamplingPeriods and pass a reference to SamplingFrequencyIndex so the actual objects you want to change, change.
CollectionViewSource.GetDefaultView(lbFields.ItemsSource).Refresh();
If your period and your frequency are both held in the same class, why not expose the list of available periods also? You can then use the CollectionView to filter your collection instead of the converter & visibility:
// 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;
}
}
精彩评论