I’ve been having issues with the TreeView in WPF. This control makes it very hard to access the TreeViewItems it’s showing.
On several occasions I have worked around the need to access a TreeViewItem, for example I’ve accepted the fact that I’m not supposed to access a node’s parent via TreeView (and am supposed to instead keep track of the parent myself). I’ve been doing this for two reasons: first, it’s obviously extremely hard to get at the TreeViewItems, and secondly, I’ve been told that it’s hard because I’m not supposed to need them if I do things right.
However, this time I really see no way around this.
Basically, all I want is, given one of my viewmodel instances, scroll the tree view to it. This is trivial if I could just get the corresponding TreeViewItem.
Am I doing things wrong again by trying to get at the TreeViewItem, or would that be the right approach?
Take a look at Simplifying the WPF TreeView by Using the ViewModel Pattern article by Josh Smith. I hope it helps.
Admittedly this is not straightforward but you can probably still do this while keeping a separation which does not require you to access the TreeViewItems knowingly. The essence in WPF is binding as already noted by Kent Boogaart in your other question, here however you need to somehow deal with events. Your view-model needs to fire a BringIntoView event of its own while the view needs to react.
The easiest method might be to add a EventSetter on Loaded to make the TreeViewItems subscribe to said event on their DataContext which should be your view-model (if it isn't you can wait for DataContextChanged).
No, I dont see in what way accessing the items of a treeview is wrong.
I think the difficulties you are encountering are because you aren't seeing the treeview as it should be.
A leaf has a parent, but no children.
A node can have a parent, and can have children.
A node without a parent is a root.
Based on these principles (SourceMaking Composite pattern) you should be able to do whatever you want using recursivity. (in both XAML and code)
I’ve come to the conclusion that it can’t be altogether wrong. The first piece of evidence comes from Bea Stollnitz’s post about ListView: if one of the WPF developers explains how this might be done, it can’t be that wrong.
The other piece of evidence comes from this highly-voted question/answer: MVVM madness. MVVM undoubtedly has its benefits, but sometimes the cost of following MVVM is so high that it’s just silly following through with it, especially in a small one-man application. Do you really want to expose IsSelected and IsExpanded the way you’re supposed to?
As a result, I felt justified to try and figure out how to expose the TreeViewItem corresponding to an item with less effort from the developer, under the assumption that they will never need the more advanced features that resulted in TreeViewItems being this hard to access (like displaying the same ViewModels in multiple different controls... how often have you needed that!...)
I posted the result of this effort as an answer on another question.
Related
I don't know if this should go on Programmers, but I thought it was relevant here.
Being a skilled WPF programmer myself, I often wonder what people were thinking when they designed WPF in terms of naming conventions.
Why would you sometimes have a property called Children for accessing the children of the control, and then sometimes have an equivalent property, just called Controls instead? What were they thinking here?
Another example is the Popup control. Instead of a Content property, it has a Child property. Why would you do that? To me that's just confusing.
So I'm wondering if there's a logical reason for it, which would probably also help me understand what the properties are called next time I need to do some speed-programming.
If there's no reason behind it, then all I can say is WAT.
I've never seen a Controls property; as for Child versus Content: Content can be any object, data for example, whereas a Child has to be some FrameworkElement in the hierarchy of the controls. To me that makes perfect sense.
I've got what I think is a fairly simple problem in Silverlight, and I'd like to solve it using MVVM principles, largely as a way of enhancing my own understanding.
Let's say I have a simple LOB app that's designed to let me load up and edit a single Employee (just an example, for the sake of explanation). In my example, Employee is made up of a number of complex objects - an Employee has a ContactInfo, a Skillset, an EmploymentHistory, an AwardsEarned, etc. The idea is that I can have this app load up a single employee and get access to a number of different editor screens. Each component of an Employee has its own editor screen.
Visually, the app just ha a left-hand nav bar and a main view on the right side. The nav bar just lets me type in an employee number and load it into memory as the "active" employee. It has a simple list of links - clicking a link should load the appropriate editor screen on the right side.
There are a couple concepts that I don't think I understand well enough, and I'm having trouble proceeding. I know there's always more than one way to skin a cat, especially when it comes to WPF/Silverlight/XAML/MVVM, but I'm having trouble thinking through all the different concepts and their repurcussions.
View-First or ViewModel First
After much thinking about MVVM, what seems most natural to me is the concept of viewmodel composition that Josh Smith seems to promote in his often-quoted article. It seems like the idea here is that you literally model your UI by composing viewmodels together, and then you let the viewmodels render themselves via typed DataTemplates. This feels like a very good separation of concerns to me, and it also makes viewmodel communication very direct and easy to understand.
Of course, Silverlight doesn't have the DataType property on DataTemplates, to many complaints: one, two. Regardless, what I see promoted much more often than viewmodel composition is a more view-first design, where the viewmodel for the view is typically instantiated in the view's XAML or via a DI container, meaning that you can't hand it any parameters. I'm having a really hard time understanding this: how is a ViewModel supposed to serve a Model to a View if I never get to tell it what data is in the model? Reaching through a view to get to its viewmodel doesn't seem to make sense either. I'm very hazy in this area but it seems the accepted answer "use a mediator/lightweight messaging framework." I'm just going through some tutorials now on the messaging system in MVVMLight and I'll be looking at similar stuff, if for nothing else than simply to understand the concepts, but if anyone can shed some light on this I'd very much appreciate it. Anything involving Unity/Prism or MEF is valid, but I haven't gotten that far in my quest for knowledge yet :-)
Instantiating Views and Selecting Them
Theoretically (I say that because SL doesn't support DataTemplate DataType), the viewmodel composition approach could make this very simple. I could have the right side of the screen be a content control whose Content property is bound to a property called ActiveEditor. A parameterized command for the hyperlinks would set ActiveEditor to a given viewmodel.
With a more view-first approach, how would I proceed with this? The first thing that comes to mind is instantiating all of the controls in the XAML of the main view.
Is manipulating the Content property of a ContentControl a good way to go for this kind of situation, or am I better off doing something like setting visibility on each individual control?
The ViewModel (VM) is written so that it is 'wired up' to the Model but has no knowledge at all of the View - in fact, this is what makes it very good to unit test (see NUnit) as it has no idea, and less does it care, whether it is being used by a UI or a Test Framework.
The VM exposes public CLR properties which implement the ICommand interface, the View, having instantiated a VM using (generally speaking anyway) its default constructor, then binds its Buttons/Hyperlinks etc to these Command properties like. So, for example, you may have a VM that exposes a CloseCommand to exit the app, the View may contain a MenuItem that binds to that command, such as:
<MenuItem Header="E_xit" Command="{Binding Path=CloseCommand}" />
Now, the VM would also expose a public ObservableCollection of objects that you want to display in your UI. Whether you populate this ObservableCollection as part of the VM constructor, or whether you do it via a UI interaction (say another Command assigned to a Button click) is up to you but the end result is that you bind a View control to this exposed ObservableCollection in XAML like:
<y:DataGrid ItemsSource="{Binding Breakdown}"/>
or equivelant for whatever control you are using to display the data (not sure off the top of my head what elements a DataGrid has in Silverlight as opposed to WPF).
Meanwhile...: The Mediator pattern is used for VM's to interact with each other, not for the View to interact with the VM. For example, you might have a custom TreeView that has its own VM on the same View as the main chart screen. In this case you could use a Mediator for the TreeView's VM to communicate with the Charts VM.
As for the last bit of your question, I think set up a basic framework using Josh Smith way in the article you mentioned and use that method to add additional ViewModels to the right hand side of your silverlight app.
Hope that helps a bit at least.
I am just getting into the Silverlight world, and wish I didn't learn WPF first so I wouldn't be so frustrated with the little things that are missing.
In WPF I was using commands (RoutedUICommand) for my view/UI to handle "events" (by event I mean something the user did) and passing them to the viewmodel.
Now in silverlight I find that I can't do it that way and on top of that there doesn't seem to be a consensus. I dislike putting code in my codebehind for my views but I keep finding myself having to do so, unless I am willing to subclass damn near every usercontrol I use. Or write a million lines of xaml for a one line codebehind statement.
And even then, I don't konw If I should use events, commands, or what seems like the best fit for me the LocalMessageSender/LocalMessageReceiver.
bottom line, is there a generally accepted approach for what must be a very common situation: telling the viewmodel what the user did?
Oh im using SL 4 if that matters.
is there a generally accepted approach for what must be a very common situation: telling the viewmodel what the user did?
Yes its called binding.
When it comes to button clicks in Silverlight 4 you should be looking at exposing a property on your ViewModel that has the type ICommand, you can then use a standard Binding on things like Button Command property.
I have been getting more involved with WPF for about a year now. A lot of things are new and sometimes it is hard to get my head wrapped around it.
At the same time I am rereading the GOF Design Patterns book.
A few times I would stop in the middle because I would realize that a certain pattern is the very one used in some WPF functionality. Whenever such a realization hits me, I feel like my understanding of the related WPF principle just took a big leap. It's kind of like an aha-effect.
I also realized that I had a much easier time understanding Prism for example because the documentation does such a great job at explaining the patterns involved.
So here is my "question" (more like an effort):
In order to help us all to understand
WPF better it would be great if anyone
who also "spotted" a design pattern in
WPF could give a short explanation.
One pretty obvious example that I found is the Routed Event:
If an event is detected by a child
control and no handler has been
specified, it passes it along to its
parent and so on until it is finally
handled or no parent is found anymore.
Lets say we have an image on a button
that is inside a StackPanel that is
inside a window. If the user clicks
the image, the event will either be
handled by it (if handling code has
been specified) or "bubble" up until
one of the controls handles it. So
each control will get a chance to
react in this order.
Image
Button
StackPanel
Window
Once a control handles it, the
bubbling will stop.
This is the short explanation, for a
more precise one consult the WPF
literature.
This kind of functionality represents
the "Chain of Responsibility
Design Pattern" which states, that if
their is a request, it gets passed
along a responsibility chain to give
each object in it a chance to handle
it. The sender of the request has no
idea who will handle it which ensures
decoupling. For a more thorough
explanation follow the link.
The purpose here is merely to show how this (seemingly old 10+ years) idea found its way into our current technology and to offer another way of looking at it.
I think this is enough for a start and hope more parallels will be collected here.
Cheers, Thorsten
I don't think it is specific for WPF but the observer design pattern seems to be the foundation on which all event handling in .Net and WPF is based.
The observer design pattern is described as "Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.". In .Net with the += operator you subscribe to such a change in state. Subsequently you unsubscribe with the -= operator.
I'd say CommandBindings are pretty important and fundamental to the way I develop.
WPF Tutorial - Command Bindings and Custom Commands
MSDN Overview
I have downloaded WPFToolkit, and I am using the DataGrid provided in this package.
I am trying to animate a row disappearance when the row is removed, but I don't know how to do it. Does anyone know how it can be done?
This is the kind of thing that can be tricky in WPF--though your boss will think it should be easy--since WPF is supposed to enable animation and striking visuals. After all, there are all kinds of awesome Silverlight/WPF demos on the web that look great and really sell the tech. Of, course what your boss doesn't know is that those demos were written just to show off the easy, flashy features. Things that are a bit different than standard, however, have a nasty way of being very difficult.
But enough ranting, I'll give you a possible approach, though there may be a far better one:
Let's assume you've bound the DataGrid to some kind of collection, and for sake of argument let's assume its a list of Foo objects, i.e. List<foo> MyFoos. Then you could add a property to the FOO class called BeingDeleted. Then in the template for your DataRowView, trigger on this property to begin a storyboard that animates a fade-out or collapse of that particular row. This is kind of gross, since it implies adding a property to the Foo object that might have nothing to do with it otherwise. You could alternatively create a special wrapper or sub-class of Foo.