How do i search for a node in very large treeview , i am using on-demand loading of nodes?
Your question is a little light on details. For example, I would be curious to know if this is a user-specified search and what the search criteria would look like. In any case, I'll take a stab at giving you a general answer to your general question:
WPF makes it easier than ever to base the view on a data model structure of your own choosing, rather than the other way around.
I would suggest creating an object model that represents the underlying data (you may have this already) and "bind" it to the tree view via data templates (specifically the HierarchicalDataTemplate). Define your search in terms of the data structure, not the view.
Related
I'm trying to improve the real-time log display of a rather complicated system. Currently there is a significant tradeoff between situational awareness (improved by displaying only high-level events) and reproducibility (which requires lots and lots of details). The obvious approach is to structure the details as a tree and allow their display to be expanded and collapsed.
The existing implementation uses just a RichTextbox. I'd like to use MVVM for my rewrite, not only because it's a best practice but also to enable behavior such as "Show details of an operation while it is ongoing, then automatically collapse them once it has successfully completed.".
As a further complication, the log records have some structure, which needs to be displayed in a columnar format. The nesting should be accomplished using the description column only (can be through pure indentation, as depicted, or using tree lines).
Can you recommend a way to map this data structure onto WPF template elements? There doesn't seem to be a way to produce a sequence of DataGridRow objects from a parent object. And because the rows do not have uniform height (some of the detail data is multiline), trying to use a WPF tree for the description and then synchronize the vertical placement of data in other columns doesn't seem feasible.
Will I have to give up on the idea of a data-bound model, and use more of a view-controller design with manual creation of WPF elements, with references to these elements such as DataGridRow stored explicitly within the in-memory tree structure, and implement collapsing and expanding by iterating through the child items and updating each descendant's Height property of the associated WPF element object?
And if I do break the data/presentation wall and use imperative coding style, is there something similar to WinForms SuspendLayout/ResumeLayout that I can use to achieve just a single layout pass per collapse, no matter how many rows changed in height?
Here is a quick mockup of the tree structure made using WPF+XAML. It's just a Grid without any document structure -- all the text elements are direct children of the Grid with manually set Grid.Row and Grid.Column attached properties. Clearly that would not be suitable for an implementation with new data and structure being generated in real time.
I would like to be able to display network-tree information (stored in hierarchical data structure), as in the example shown in here:
In the diagram, I have a number of hosts (top-level nodes) - one of which is considered the 'Master' and therefore rendered differently from the other top-level nodes. Each node can have multiple sub-nodes (probes). The lines between the nodes show connections and if any of the connections goes down, the line changes as shown between Hostname2 and Probe2.3. Any node selected (host or probe) should also be rendered differently.
I am using Prism/MVVM and I'm trying to keep the code as clean as possible, but I'm not sure of the best way forward for displaying this data.
I have considered using a TreeView but I cannot think of a clean way of creating the links between nodes. I also considered creating a custom panel, but I'm not sure that's the most appropriate and wouldn't know where to start. Then I thought of creating a custom ItemsControl, as it would be nice to use the DataTemplate and HierarchicalDataTemplate. I could also create a UserControl that contains a canvas and do everything in the code-behind there but it doesn't feel the best way.
I'd be grateful for opinions, example code, links or any suggestions you may have.
You're in luck, last year I had to write something very similar for my current job. I can't give you any of my code but I can lead you in the proper direction.
I found a directed graph collection class available here: http://msdn.microsoft.com/en-us/library/ms379574(v=vs.80).aspx#datastructures20_5_topic3.
I also use a Radial Panel I found on MSDN: http://msdn.microsoft.com/en-us/library/ms771363(v=VS.90).aspx. This allows multiple nodes to draw in a geometric shape. So if you have 3 nodes, they draw a triangle, 4 a square, 5 a pentagon, etc...The more nodes you have, the more the layout becomes a circle. This wouldn't work for you, but if you follow the link it shows you how to create a custom panel with a custom layout. It could be beneficial.
I then used a Canvas as the stage, with the RadialPanel as the Canvas' child element. Each node is just a WPF UserControl with an ellipses background that is added to the RadialPanel. The directed graph collection then become a collection of node view models. I store where the node is connecting, almost like a linked list. This allows me to traverse my graph collection easily without having to iterate each node to find the nodes I'm looking for.
There are some tricks involved in drawing to ensure the layout is proper, especially when drawing your connecting lines. See this StackOverflow post I made: WPF and C# - Issue with GeneralTransform and UIElement.TransformToVisual. It has a link to an image of my node graph so you can compare our graphs.
This obviously isn't everything, but I think it's a good start. For me, I couldn't really override any current controls to do exactly what I needed, so I went the hard way. The trade off is a lot of work in the code-behind and view models, but I also control the major aspects of how it's drawn. I this helps.
I'm making a UI where the user can add and store links to their favourite Youtube videos. Very similar to a favourites folder in a browser, but just for Youtube videos.
I want the links displayed in a treeview, so that they can be catalogued into categories and sub-folders, etc. Sort of like this:
Videos
|---Music Videos
|---Music video 01
|---Music video 02
|---Music video 03
|---TV Shows
|---TV show 01
|---TV show 01
What I'm struggling with most at the moment, is working out how the user can store this data once the UI has closed. I've been looking into xml binding, but I can't seem to create a decent xml schema that seems to work properly with the treeview.
Also, how would I go about storing the URL along with the video name, but have the treeview display only the name?
I'd be very grateful for any pointers as to the best way to go about this. Is there a better way? It's all very confusing.
Thanks very much.
Good data architecture is a non-trivial issue, i can just offer some thoughts of mine but cannot guarantee that they are all a good idea.
Firstly would not recommend working directly with XML data, it gets very inconvenient if you try to do more complex things.
You can serialize your data to XML, but you should be aware of its limitations and side-effects, there are questions to be found here on SO which try to compare the various methods of serialization, you might want to look for those as other formats might be more suitable. Two aspects of XML are quite apparent for example:
Huge file-size overhead due to the tags & and text-based data
Unlike binary serialization the data is more or less human readable and transparent
In any case i would use a database or a normal object model and serialize/deseriale that for storage.
If you want to allow sub-categories you may want to use a composite pattern, you then can have an object Video and Category, both implementing the interface IVideoComposite, where Category has a property Children of type ObservableCollection<IVideoComposite> for example.
You then can use implicitly typed datatemplates (a HierarchicalDataTemplate for Category) to create the items in your TreeView. (For the one of Category you will then bind the ItemsSource to Children)
I have an old VB6 application. I want to recreate it in VB.Net using WPF. But I am a bit confused about the "Model View Controller"-pattern. I have two books about design patterns (GoF and J.Bishop) afair this pattern is indeed not mentioned inside one of the two books. I have also searched the internet I found some java-examples. But I have still no clue how I should use MVC-Pattern (should I?) in my new WPF-application.
Let's say for example my model (in fact it is more complex) is only a wheel rim (circle) with the properties Manufacturer, Diameter and Depth. The user should be able to modify the properties using textboxes and ComboBoxes.
Could somebody create a small example that explaines the MVC-Pattern with WPF?
Of course I like reusable classes to have a feasible concept throughout the whole application.
thanks in advance
Oops
Here's a "brief" description of what the MVC pattern is and how I would apply it to a WPF application.
(I might have a few details slightly off since I've mainy hacked in Silverlight but the concept is similar enough.)
Basically, the idea is to separate concerns and define interfaces between the different parts of an application, with the goal of keeping the code structured and maintainable.
The Model in your example would be pretty much exactly as you described the wheel rim - a WheelRim class with the various properties defined in suitable data types. I would put the model i an separate assembly to keep it apart from the other code, but you can settle for just keeping the model classes in a "Models" folder. The model would also have a "twin" in a database, the model classes being pretty much one-to-one-mapped to tables.
(You might wanna have a look at Linq2SQL or Entity Framework, if the database is defined you can pretty much get the model for free along with suitable database access code.)
The View would be the actual WPF xaml files - Defining the Grid or Canvas or what have you. On the WheelRimView there would be labels and textboxes for displaying or accessing the different properties, perhaps along with product images and the like. The code behind for the view would have all the relevant event handlers (start, button_click and so on) for getting the data from the fields and passing them to the controllers.
The Controller would be any "handler code" that you would use to manipulate the data. We're talking the basic CRUD operations here, along with validation and the like. Also, the controller layer would be responsible for compiling the data in a format that can go seamlessly into the View. The WheelRimController hence would have methods like "GetWheelRimList", "GetWheelRim", "AddWheelRim", "ModifyWheelRim" and "DeleteWheelRim". The methods take the values as in parameters and manipulate the model objects accordingliy. the
I would recommend keeping the code-behind of the xaml files free from any "controller"-ish code like validation, aggregation and the like - the code behind should basically only take the values from the textboxes, listboxes and such and send them on "as is" to the controller methods for processing. Also, you should keep any data formatting code to a minimum when getting data for presentation (i.e., no filtering or translating in the view).
A typical use case of "User opens a wheel rim and edits the diameter" would play out thus in code:
User clicks "Edit" on a list page. The WheelRimView page loads.
The WheelRimView.Load() method (or corresponding) calls WheelRimController.GetWheelRim(wheelRimId).
WheelRimController.GetWheelRim(wheelRimId) gets the corresonding data from a database table and populates the properties of a WheelRim object, which is returned to the WheelRimView.
The WheelRimView inserts the property values into the labels and textboxes.
The user changes the diameter value and clicks the "Save button.
The WheelRimView.Save() method calls the WheelRimController.ModifyWheelRimDiameter(wheelRimId, diameter) method.
The WheelRimController.ModifyWheelRimDiameter(wheelRimId, diameter) method parses the diameter (if it is a string) and loads the model object. It applies the modified value to the model object and saves it into the database.
The WheelRimController.ModifyWheelRimDiameter(wheelRimId, diameter) returns a status code to the WheelRimView (for instance a predefined numeric stating any validation errors) to report the success of the save.
The WheelRimView displays a result message (hopfully "saved") to the user.
I hope that clears a few bits up.
Bevcause of the rich binding support available, WPF (and Silverlight) are well suited to MVVM (Model-View-ViewModel). MVVM is an extension of MVC that uses a view model to bind the current state of a view, instead of manipulating the view directly.
There are a bunch of MVVM frameworks available, as well as Microsoft's own Prism framework (which is arguably more useful if you have a larger, modular application).
WPF is probably more well suited to MVVM (Model-View-ViewModel). I'd recommend reading this MSDN article on MVVM and, perhaps, following their advice. There's also a nice collection of links I found on the Bryant Likes blog.
In my WPF MVVM application my model is a complex tree of Model objects wich constantly changes at runtime. Model instances come and go at runtime, change their position within the tree and of course change their many properties. My View is almost a one-to-one visual representation of that tree. Every Model instance is in 80% of the cases also a node in the tree.
My question is now how I would design the ViewModel around this? My problem is that there are quite a lot of different Model types with each quite a lot of properties. If I understood MVVM corretcly the view should not communicate with the Model directly so this would mean that I would have to create a ViewModel type for each Model type and have to rewrap each property of the Model type in the ViewModel.
Also the ViewModel would need to "bind" to the propertychanges of the Model to pass it along to the view (using wpf datatbinding). I would need some factory that creates and introduces a ViewModel instance for each Model that appears anew and I would habe to dispose each ViewModel instance when the corresponding Model disappears. I end up keeping track of all instances I created. It is unbelievable how much bloat code is generated dues to this double wrapping.
Is this really a good approach? Each entity and each property more ore less exists twice and I have a lot of extra code keeping Model and View in sync. How do you handle this? Is there a more clever way to solve this?
Does anyone have a reference/sample implementation for this that does it better than I do?
I think you may run into trap of paradigm if you follow this path. MVVM is nothing more than a pattern, which simplifies development in WPF world. If it doesn't - don't use it or revise your approach. I wouldn't spend 80% of my time just to check the "Using MVVM" field.
Now back to your question. Correct me if I'm wrong, but it sounds like you are looking at MVVM from opposite direction: you don't need Model to ViewModel one-to-one correspondence. Usually you create ViewModels based on your View first, and only then on a Model.
Generally you look on a screen mockup from graphic designers, and create corresponding ViewModel, which takes all necessary fields from the Model, wraps/modify/format/combine them to make View development as easy as possible.
You said that your View is almost one-to-one visual representation of the Model. In this case it may have sense to create a very simple ViewModel which exposes root object of your model-tree, and let View consume model directly via that property. Then if you need some View customizations or commands processing you can delegate that to ViewModel.
Sorry for very vague answer. Maybe if you ask more specific question we could dispel the confusion :)...