In my WPF app, I have an ObservableCollection<MenuItem>
which is dynamically updated to contain various category items. When the screen loads, everything is fine but changing the collection while the screen is up, and calling RaisePropertyChanged
for the collection doesn't update the context menu.
It appears that possibly, context menu's are only loaded on control loading and can't be changed dynamically?
UPDATE: This code is dynamically creating a sub context menu based on items the user is adding or removing. My question here is why isn't the DocumentExplorerMenuOptions getter being called when RaisePropertyChanged is being called? I see RaisePropertyChanged being called but the getter never gets asked for anything.
public ObservableCollection<MenuItem> DocumentExplorerMenuOptions {
get {
return new ObservableCollection<MenuItem> {
new MenuItem(localizationProvider.Takeoff) {
Command = new DelegatingCommand(x => windowManager.ShowTakeoffWithGrid(context, selectedDocument, documentBagTasks))
},
new MenuItem(localizationProvider.TakeoffImage) {
Command = new DelegatingCommand(x => windowManager.ShowTakeoff(context, selectedDocument, documentBagTasks))
},
ClassificationMenuItem
};
}
}
MenuItem classificationMenuItem;
public MenuItem ClassificationMenuItem {
get { return classificationMenuItem; }
set { classificationMenuItem = value; }
}
void BuildClassificationsContextMenuItem(ICategoryBag categoryBag) {
ClassificationMenuItem = new MenuItem(localizationProvider.ClassifyAs);
if (categoryBag开发者_运维技巧 == null) return;
foreach (var category in (from category in categoryBag.Categories select category).OrderBy(x => x.Name)) {
AddCategoryMenuItem(category);
}
RaisePropertyChanged(DocumentExplorerMenuOptionsPropertyName);
}
void RemoveCategoryMenuItem(Category category) {
ClassificationMenuItem.Children.RemoveAll(x => x.Text == category.Name);
RaisePropertyChanged(DocumentExplorerMenuOptionsPropertyName);
}
void AddCategoryMenuItem(Category category) {
var categoryMenuItem = new MenuItem(category.Name);
ClassificationMenuItem.Children.Add(categoryMenuItem);
foreach(var value in category.Values) {
categoryMenuItem.Children.Add(new MenuItem(value.Name) { Command = new DelegatingCommand(x => classifier.Classify(new ClassificationArguments(category, value, new List<Document>(documentExplorer.SelectedDocuments).ToArray()))) });
}
RaisePropertyChanged(DocumentExplorerMenuOptionsPropertyName);
}
The ObservableCollection property is not setup correctly. You have added everything in to the getter of that property, that doesn't really work. Try creating a private member and instantiate that on the constructor itself and add those entries there. In this case you are kind of re-instantiating the ObservableCollection for each of your View loading, because getter can get called many times.
This issue was resolved on a similar query by me. Hope this resolves your issue.
ContextMenu bound to ObservableCollection<MenuItem> does not refresh data
This is strange, if I'm reading your code correctly. Is there a reason that you can't maintain the collection and modify it (as opposed to re-creating it) so that you don't need to RaisePropertyChanged
at all? That's what ObservableCollection(of T)
does, after all.
As I'm reading it, it might as well be an IEnumerable(of T)
.
(Creating a new ObservableCollection(of T)
in a property getter is almost always a mistake. A ReadOnlyObservableCollection(of T)
makes a lot more sense in that context.)
精彩评论