Okay so I'm currently binding a ContextMenu
ItemsSource
to an ObservableCollection
of lets say TypeA
The following code is within the singleton class DataStore
private ObservableCollection<TypeA> TypeACollection = new ObservableCollection<TypeA>();
public ObservableCollection<TypeA> GetTypeACollection
{
get { return TypeACollection; }
}
public ObservableCollection<TypeA> GetFirstFiveTypeACollection
{
get
{
return TypeACollection.Take(5);
}
}
Now I've already successfully bound an ItemsControl
to GetTypeACollection
with the following XAML code:
The following code is within the MainWindow.xaml
<ItemsControl x:Name="TypeAList" ItemsSource="{Binding GetTypeACollection, Source={StaticResource DataStore}, UpdateSourceTrigger=PropertyChanged}" >
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<User_Controls:TypeAUserControl Type="{Binding }"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
This works as expected, showing the TypeAUserControl
, correctly formatted as intended with the data from TypeA
Now when i try to repeat this on a ContextMenu
MenuItem
by binding the ItemsSource
to GetFirstFiveTypeACollection
i initially see the expected results however upon deleting a TypeA
object the MainWindow ItemsControl
is updated where the ContextMenu
is not.
I believe this is due to the fact that the binding itself is between the ContextMenu
and a 'new' ObservableCollection<TypeA>
(as seen in GetFirstFiveTypeAColletion
).
I have also attempted this through use of an IValueConverter
The following code is within the class ValueConverters
public class ObservableCollectionTypeAResizeConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
ObservableCollection<TypeA> TypeACollection = value as ObservableCollection<TypeA>;
return TypeACollection.Take(System.Convert.ToInt32(parameter));
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return null;
}
}
Using IValueConverter
<MenuItem Header="First 5 Type A" Name="MI_FirstFiveTypeA"
ItemsSource="{Binding DATA_STORE.GetTypeACollection, ConverterParameter=5,
Converter={StaticResource ObservableCollectionTypeAResizeConverter},
Source={StaticResource DataStore}}"
/>
Using GetFirstFiveTypeACollection
<MenuItem Header="First 5 Type A" Name="MI_FirstFiveTypeA"
ItemsSource="{Binding DATA_STORE.RecentTimers, Source={StaticResource DataStore},
UpdateSourceTrigger=PropertyChanged}"
/>
I've no idea what to try and do next or how i should be doing this, Any help would be greatly appreciated!
Okay so I have changed the following
DataStore.cs
private ObservableCollection<TimerType> TimerTypes = new ObservableCollection<TimerType>();
public ObservableCollection<TimerType> getTimerTypes
{
get
{
return new ObservableCollection<TimerType>(TimerTypes.OrderByDescending(t => t.LastUsed));
}
}
public ObservableCollection<TimerType> RecentTimers
{
get
{
return new ObservableCollection<TimerType>(TimerTypes.OrderByDescending(t => t.LastUsed).Take(5));
}
}
public event PropertyChangedEventHandler PropertyChanged;
// Create the OnPropertyChanged method to raise the event
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
//THIS IS IN THE ADD METHOD
TimerTypes.Add(timer);
NotifyPropertyChanged("getTimerTypes");
NotifyPropertyChanged("RecentTimers");
NotifyPropertyChanged("TimerTypes");
//THIS IS IN THE REMOVE METHOD
TimerTypes.Remove(Timer);
NotifyPropertyChanged("getTimerTypes");
NotifyPropertyChanged("RecentTimers");
NotifyPropertyChanged("TimerTypes");
MainWindow.xaml
<ItemsControl x:Name="TimersList" ItemsSource="{Binding Path=getTimerTypes, UpdateSourceTrigger=PropertyChanged}" >
MainWindow.xaml.cs
//Lists are populated in DataStore.cs before this.
DataContext = DataStore.DATA_STORE;
InitializeComponent();
NotifyIcon.xaml
<MenuItem Header="Recent Timers" Name="MIRecent" ItemsSource="{Binding RecentTimers, UpdateSourceTrigger=PropertyChanged}"/>
NotifyIcon.xaml.cs
DataContext = DataStore.DATA_STORE;
InitializeComponent();
So everything binds correctly at start but when a TimerType
is deleted the PropertyChangedEventHandler
is always NULL. I thought this was a DataContext
issue but I'm pretty sure I have the DataContext
and all of the Bindings
correct now?
private static readonly DataStore Instance = new DataStore();
private DataStore() { }
public static DataStore DATA_STORE
{
get { return Instance; }
set { }
}
Unfortunately, by using Take
(or any of the LINQ methods) you get a straight IEnumerable
back. When you have bound to it, there is no INotifyCollectionChanged
so changes to the collection will not cause the UI to update.
There's no real workaround due to the lack of INotifyCollectionChanged
. Your best bet is to raise PropertyChanged
against your "subset" property when you add/remove items to force the UI to renumerate the IEnumerable
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With