I am creating a menu that will have its menu items injected into it from different modules (I am using the Composite Application Library: Unity, Prism).
Example:
File
- Open
- New
- A (injected from ModuleA)
- B (injected from ModuleB)
- C (injected from ModuleC)
- Exit
Because I don't know which items will be injected, I need to somehow sort my Menu Items. I am trying to do this now by creating a RankedMenuItem that inherits from MenuItem. RankedMenuItem has one additional property, Rank, which is an integer.
I set the "File -> Exit" menu item to be rank 1000, and "File -> Open" to be rank 0, so that Exit will always show up at the bottom of the File menu, and Open will always show up at the top.
The trouble I'm having is that I can't figure out the best way to sort the menu hierarchy. I can sort the top level easily using a CollectionView, but I can't figure out how to apply it to the subitems.
Any advice would be much appreciated.
By default the MenuItem.ItemsSource can contain any collection-based set. This can be a sorted list, for example, or an collectionviewsource. If the items in the collection are domain-specific (e.g. not MenuItem objects) then your task may be less-than-trivial. Based on your description it sounds as though your modules register a simple MenuItem object directly into the Items of the "New" MenuItem, thus making it impossible to perform a sort. If that's the case, my suggestion is to have something like ObversableCollection which items are added/removed via, and use that via a CollectionViewSource attached to the MenuItems property of the "New" menu-item. This should allow you to sort menu items added dynamically by other modules (though, how you implement the sort is up to you, e.g. requiring a RankedMenuItem from the modules, or you could simply sort alphabetically with some product-specific "weighting" to ensure some menu items are always sorted above/below other "known" menu items.)
Hope that helps.
Related
I have two ObservableCollections in my ViewModel. Both of same generic type.
Window has two ItemsControls each with ItemsSource bound on its own ObservableCollection from ViewModel.
Both use same same ItemTemplate. This ItemTemplate is very complex user control.
It's all done by the book.
In some cases, I move item from one collection to another. UI updates correctly. However, as control is complex, it needs about 1-2sec to render when it is recreated in new ItemsControl. And since this happens on drag and drop operation, it is not user friendly.
What I would like to do is to somehow preserve existing instance of ItemTemplate from source ItemsControl and reuse it in destination. I don't know if it is even possible, I couldn't find anything about it online.
I believe setup is fairly simple, but if needed I'll write some simplified version of code (I can't share the real code).
Thanks for any help.
What I would like to do is to somehow preserve existing instance of ItemTemplate from source ItemsControl and reuse it in destination. I don't know if it is even possible, I couldn't find anything about it online.
I am afraid it is not. When you disconnect an element from the visual tree and then add it back to a different parent element at a later stage, all elements that make up the control will be re-rendered.
This seems to be a problem that I encounter regularly: I have a list control, in this case a DataGrid, and the items in the control come from a web service. My application regularly asks the web service for the latest list of items. Compared with what my application currently has, the resulting list may have additional items, fewer items, or different details for existing items.
How do I update my control (ie: my data grid) without:
1) De-selecting the user's currently selected items.
2) Resetting the ordering that the user may have set on various columns.
3) Doing anything else that makes it jarring for the user.
4) Incorporating too much code, turning it into an unmaintainable mess.
Am I simply going about this whole thing wrong? It seems to me this scenario should be simple to address with something as versatile as WPF.
My current thinking is to use INotifyPropertyChanged on each item, and an ObservableCollection. Then, for each item in the list, update every property when we do the refresh (adding and removing items from the collection as necessary).
You are right, use ObservableCollection
1) De-selecting the user's currently selected items.
You can use either CollectionViewSource.GetDefaultView(rootElem.DataContext).Current or create a SelectedItem property, and bind it to the UI element. I prefer SelectedItem because it is less view related. For deselecting just set it to null.
2) Resetting the ordering that the user may have set on various columns.
You can easily swap two elements in ObservableCollection, and that change immediately will appear in the view.
var tmp = myObsCollection[i];
myObsCollection[i] = myObsCollection[j];
myObsCollection[j] = tmp;
Also you can use keep order property in your items, configure sorting in CollectionView, and just rearrange orders when needed and call view.Refresh();
3) You don't need to update all properties for updated items, just find the correct item index and replace it with new one, WPF will update automatically
myObsCollection[fIndex] = updatedItem;
Use the same logic for delete/add elements
I'm working with ListCollectionView objects to display lists of items. Currently, I'm building a screen that has two of these lists - one, completeList, holds all available items, the other one, sortedList, holds a subset of them with the item order being relevant. Possible actions here are
add or remove any of completeList's items to/from sortedList
move items up or down in sortedList
save the content of sortedList.
Now, my question is this: is there any possibility to insert items into sortedList at a defined position?
Right now, they will always be added at the end of the list, regardless of the currently marked item, and I didn't find a way around it - apart from the obvious dirty hack, which would have me store all items after the desired position, remove them from the list, add the new item, then re-add all stored items in the correct order.
Does ListCollectionView offer any such functionality, or is there another CollectionView class that would do the trick?
You're actually asking for something that's a logical contradiction. Suppose I have a ListCollectionViewsorted alphabetically:
American
Continental
Festival
Imperial
Tower
Worldwide
Should I be able to insert Luxor between American and Continental? Not if the view is sorted. There's only one place that item can go. And where it appears in the view is independent of where it might appear in the underlying list.
Without knowing more about your application, it's hard to know exactly what to suggest. But if a collection view is sorted, the way to make an item appear at a specific place in the view is to assign its sort key(s) a value that will, once the view is refreshed, cause it to appear in the desired location.
A fairly trivial (and generic) way of doing this is to add a DateTime property to the data item class, set it to DateTime.Now in the item's constructor, and make it the last sort key that the view uses. Then, when adding a new item, set its other sort key properties to the value of the currently selected item. If you do this, new items will always appear in the appropriate place, so long as you don't change the values of any of the sort key properties.
Having said that, from the other features you want to support, I believe that you shouldn't be using a ListCollectionView at all for what you're calling sortedList. This list isn't sorted. It's ordered, which is not at all the same thing. When the user moves an item up in the list, you actually want to change its position.
What you probably want to do is implement the list as an ObservableCollection, and wrap it in a view model class that exposes Items, SelectedItem, AddNewCommand, MoveUpCommand, MoveDownCommand, and SaveCommand properties. Then you can bind the ItemsSource and SelectedItem properties of a ListBox or ListView to Items and SelectedItem properties in the class, and bind buttons or hyperlinks or whatever in the UI to the commands. The commands will manipulate the Items property, using Remove and Insert, and since the Items is an ObservableCollection, the UI will stay in sync.
I'm new to the "Telerik"-controls and I have a few questions! First of all, I'll give you a small resume of what we want to achieve and how I did it for now.
The customers has several clients who come to present themselves and they need to fill in their qualities (language skills, education, ....). Therefor we've created some templates (that already contains some crucial data). The templates can be hierarchical => Language Skill Dutch has two children : "Writing", "Speaking". They see that in an Hiearchical treeview (for now).
If they select the item in that tree, they automatically create a quality (with the templateid, contactid, etc...) for that type of template. Each time they call the treeview for that contact, the template who has a quality will be checked! And if they click on "Edit", they'll be able chaging some info of the quality.
That's in short what it does now and what's behind it. Now, they wanted a nicer looking method without having popups and such (everything in one screen). Then i found the "RadTreeList" of telerik. But for now I'm having the following problems :
The root of the tree can't be selected (best would be that the checkbox is hidden) => how do I achieve this?
Is it possible to hide the "EDIT"-button on the root? The root should never be selected on his own (no qualities for root elements).
So the big question, how can I take an item while looping through the whole treelist collection and say that I don't want to show checkbox and such?
With my treeview I iterated through all the nodes and then I did the needed modifications. But 1 => It was slow, 2 => It looked that nice, 3 => It didn't match they look of the CRM 2011.
What i've already achieved is showing everything hiearchical and select the "Node-Templates" (if I can call it so) that contains Qualities.
Hopefully you have enough info... If there are better alternatives, I'm open for everything, but it's kind off urgent, cause we'll have a demo-session soon :)
Info => It has to be in ASP.NET (C#)
It is true that you cannot select the 'root' of the treelist, but you can place an item in the first column to add new items at root level as illustrated here: http://demos.telerik.com/aspnet-ajax/treelist/examples/dataediting/net35automaticdataediting/defaultcs.aspx.
To hide the edit button for root level items, listen to the ItemCreated event, locate the edit button in the root items only and set its Visible property to false. This should work for checkboxes or other server controls inside the treelist rows and you do not have to perform explicit loops through the items later on.
I have a problem using Infragistics UltraTree control.
I need a way to add a specific context menu to an UltraTreeNode.
I saw that there is a contextMenu property for the UltraTree, but I need a unique one per each node.
what is the best way for doing this in C#?
I've recently had to do this with a regular TreeView. Since infragistics.UltraTreeNode has a context menu just like the regular TreeNode, I'm guessing the technique will be the same.
Here's how I did it:
Step 1. Assign the context menu of interest to each node that should recieve it. This should be done while populating tree nodes.
Step 2. Intercept the Opening event on the context menu(s)
Step 3. Rebuild the contents of the menu in the "contextMenu_Opening" event handler. Only do this for a context menu object that will be shared among different node types. You can also add all items you want to the menu, up front on the treeview or containing controls construction, then hide or show them through the Visible property. This is really a matter of personal preference at this point.