|
jgalak wrote: My initial thought is that I need 4 views (All Clients, All Users, Selected Client, Selected User), and 2 view models (UserVM and ClientVM). So my first question is: Am I setting this up right? Or should there be 2 more VMs (UserListVM and ClientListVM)? Or vice-versa, 2 views (list and detail) and 4 VMs?
A ViewModel is the model of a View - so you need 4 ViewModels - you CAN have more than one View for a ViewModel if each View is a diffrent visual interpretation of the logic in the ViewModel - but generally I like to think of the viewModel as being the specification of the View's functionality - so, yes, 4 VMs
jgalak wrote: However, since my model class is created by the Entity Designer, it doesn't (as far as I can tell) implement it. How do I deal with this? I suppose I can just use a timed "refresh" event that manually re-reads from the DB, but that seems inelegant.
properties within the ViewModel should implement INotifyPropertyChanged. some simplified tutorials implement it in the Model but (IMHO) this is entirely the wrong place as far as MVVM goes.
So your Model has a CustomerName property (a plain, old fashioned property). Your ViewModel may also have a CustomerName property, but this one implements INotifyPropertyChanged. The Getter on this VM property can just grab the string straight from the Model's property. And, indeed, the setter can also set the Model's property directly. so the Vm is just presenting the data in a bindable way to the View
jgalak wrote: Next, using the setup from that tutorial, how do I initialize the view? I've built a UserView control (and placed it into my main window) and a UserVM class, all of which bind together with XAML, but when I run it, the control is (understandably) blank. At what point should a User be provided? I'm thinking an overloaded constructor of the UserVM class (using no parameters for a "add user" action, and a single "User" type parameter for an "edit user" function), is there a better way?
I would think that you would first present a list of Users from which the user can select - or click a button to add a new one. so the userListViewmodel would be the thing to first populate
jgalak wrote: Finally, how do I trigger a write back into the DB once a change has been made (when the user clicks the save button)?
usually your Vm would implement a command, bound tot he button, and would take the data in itself (or in the Model, if you've been updating as the properties in the Vm change) and so your Vm handles the save
If you look at my article (link in the sig) I take you through a WPF MVVM application to maintain customers. It may not be the answer to everything, but it should show you at least one way of looking at it - and a working example is there for D/L to be played with
|
|
|
|
|
I have a misunderstanding about RepeatBehaviour. I'm experimenting and I have this XAML embedded in a Canvas inside a System.Windows.Window. I expected the colors to transition from Blue to Orange and back again, followed by Green to Purple and back again, and then for the process to repeat until the Storyboard duration ran out. However, it only performs one cycle and then stops - on green.
What am I doing wrong...
<Button Name="butPlay"
Click="butPlay_Click"
Width="96" Canvas.Left="136" Canvas.Top="191" Content="Play" Height="40" >
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard >
<Storyboard Duration="1: 0: 0"
RepeatBehavior="5">
<ColorAnimation Storyboard.TargetProperty="Color"
Storyboard.TargetName="rctPlayBrush"
From="Blue" To="Orange"
Duration="0: 0: 1"
AutoReverse="True" />
<ColorAnimation Storyboard.TargetProperty="Color"
Storyboard.TargetName="rctPlayBrush"
From="Green" To="Purple"
Duration="0: 0: 1"
AutoReverse="True"
BeginTime="0: 0: 2"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
Whilst I realise the colour scheme leaves a little to be desired, can you help me the technical rather than esthetic aspect?
ps. How does one stop colon-zero ( )being displayed as a smiley? (hence the spaces after the colons in the code)
Paulustrious
Email: codeproject who-is-at paulcotter.com
modified on Saturday, May 28, 2011 5:49 PM
|
|
|
|
|
What did you mean by the "RepeatBehavior="5""? Repeat 5 times? If so it should be RepeatBehavior="5x". Or did you mean 5 hours?
Anyway, the Storyboard timeline is 5 hours, but the total animation time for the storyboard is only 4 seconds, so it appears to stop after one storyboard iteration because it's spreading 4 second long animations over the a 5 hour timeline. Make sense?
So my suggestion is get rid of the "Duration" on the storyboard (the default value of "Automatic" for Duration should be what you want here) and adjust RepeatBehavior the way you want it - either an iteration count, a timespan, or "Forever".
Paul R Cotter wrote: ps. How does one stop colon-zero ( )being displayed as a smiley? (hence the spaces after the colons in the code)
Evil smilies...they cannot be stopped...
Mark Salsbery
Microsoft MVP - Visual C++
modified on Saturday, May 28, 2011 6:50 PM
|
|
|
|
|
I want to create a silverlight application with the ability to radically change the look and feel with themes. So could I just place contents controls on every single page and then just load the actually page from resource files at runtime. Is there anything wrong in doing this?
|
|
|
|
|
|
The Silverlight toolkit support themes, so you can take a look at theming as well.
The funniest thing about this particular signature is that by the time you realise it doesn't say anything it's too late to stop reading it.
|
|
|
|
|
I wasn't asking how to implement theming. I was aksing if there is anything wrong with having every page within your application a single content control.
Doing this would enable you to radically change the theme of your application not just the theme of controls but also the location of the control within the page or even create new controls at runtime that your application knows nothing about. Anyone have any views on this?
|
|
|
|
|
There's nothing inherently wrong with this approach, but there's a lot of plumbing work that you are going to have to take control of.
|
|
|
|
|
I am using ınkcanvas.
BUT dare need to draw an ellipse movements.
Can I use the stylus point
|
|
|
|
|
Kind of a newbie question
I want to use the same usercontrol on several Silverlight pages. In creating the usercontrol I've bound it to a ViewModel and wired up all the textboxes and such to the VM's properties. Each Silverlight page has its own 'parent' viewmodel that manages the selection of data from the database that I'd like to use to populate that page's version of the usercontrol's viewmodel.
So...how do I best pass the data in from the page's ViewModel to the usercontrol's ViewModel?
|
|
|
|
|
Strictly speaking, you wouldn't pass the data in. The reason that this is a no-no is that you've introduced a coupling here where the parent ViewModel has to know what views are associated with it, and hence the ViewModels that are associated with those views. This is a real no-no.
Remember that MVVM is based on the concept of a ViewModel wiring up to a Model; this tells you that your child VM needs to hook into the same data as the top-level VM. There's no real reason though, that this has to be a database. What you could do is have a top-level entity which is responsible for reading a whole bunch of data in that your top level VM uses, and your child VMs could also use this source of data.
|
|
|
|
|
Thanks Pete. A little history is that this started out as a single SL page with one way for users to select parameters that filtered the data to be returned. Then came the suggestion that some users would want a markedly different way of filtering but the additional controls ate up lots of screen space. No problem, thinks I, refactor out the common portions of the screen (the portion that deals with presenting and editing the data) and create a user control with its own VM with all the editing logic, etc., and drop the user control onto each of the 2 pages.
OK, at the page level my VM ("ParentVM") reacts to the user's filtering steps, retrieves the data, and populates an ObservableCollection that is a property of the ParentVM. It's that ObservableCollection property that I want the ChildVM to access, so that the usercontrol can present the data to the user and the ChildVM can take over. Where I'm stumbling is getting the ChildVM to see the ParentVM's ObservableCollection property.
Am I looking at this bass-ackwards? Or is the approach OK but I'm overlooking something elementary?
Thanks
|
|
|
|
|
A simple mechanism to achieve this is to have the parent level VM manage the population of the data in a model. As long as the child can see the data in the same instance of the model, then it can retrieve and manage it's own ObservableCollection based on this data. All you would need to do would be to hook into the CollectionChanged event on the model to know that you had to retrieve the new data items (although I would normally look at using a more explicit event because the CollectionChanged gets raised on every change to the collection, and you might want to wait for the data to be updated completely before you react to the change).
A mechanism such as making the model class static would ensure that all VMs could see the same instance, and react to changes in it.
So, why am I recommending this approach rather than binding to the VM? After all, you could achieve a similar effect that way. By going with this approach, I've looked at completely decoupling the VMs - ensuring that they don't need to know about each other and, more importantly, ensuring that issues such as you have faced here are, to a large extent, minimised as you change the VMs. Remember, the VM matches what's in the View, so you don't want to have to rejig things around again just because you move something from one view to another.
|
|
|
|
|
I use a different approach and I have the nasty feeling it may be incorrect.
I have a navigate frame where the filter lives on the parent (which is itself a navigation frame) and when the user makes a selection the required control is displayed. Where I am probably most in error is that my VMs are static and the child VM gets some information from the parent VM, SelectedItem etc.
I have also been known to have the VM service multiple view (view and dialog).
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
Thanks for the input Mycroft. I'm not a programmer - but I'm closer to being one than anybody else in our department so this stuff falls to me. One of the things I've found frustrating in learning MVVM is that there's plenty of info on the web about how to do this task or that task in MVVM, but not much that explains WHY, at least not in terms that a novice can get their head wrapped around.
I thought about trying an approach very similar to yours but stalled on pursuing it. The downside to not doing this full time is that doing things by trial and error is REALLY time consuming because, for me, there's lots more error than there would be for somebody more fluent and accomplished.
Since Pete responded, I have had only a few minutes to even think about what he suggested, so no real progress on it.
|
|
|
|
|
Duke Carey wrote: I'm not a programmer
Considering this I then ask myself why you decided to use MVVM, as it is strongly focused on testing which is very much a professional programmers criteria.
I don't have a requirement to do a lot of testing myself but have found that MVVM has numerous other benefits and it does dictate a nicely structured solution. Getting the structure just right is the real challenge.
Sometimes (often) the why will not make sense unless you have the same requirement and some people make stuff overly complex just for the sake of complexity. I'm pretty sure I have bastardised the MVVM concepts but then I just want the bloody thing to work and I do like simple, even if it means breaking a design principle (one of the reasons I am no longer writing articles).
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
Mycroft Holmes wrote: I do like simple, even if it means breaking a design principle (one of the reasons I am no longer writing articles).
I think knowingly breaking a principle for a good reason is a good thing - after all, someone decided upon a principle, it wasn't handed down on some rock tablet from a burning bush (sorry, religion not my strong point - but you see what I mean)
So if you have need to break a design, with knowledge of the design and knowing you are breaking it, then I think you should not only do so, but you should also write articles specifically about it.
I know I have seen people using MVVM write pages of XAML and C# code because they don't want to write any code-behind - although the code-behind is probably three lines and makes perfect sense. I say, break the principle by all means- but break it with the knowledge that you are breaking it, and why you are breaking it, and do so with head held high. (cue stirring music(
|
|
|
|
|
_Maxxx_ wrote: I say, break the principle by all means- but break it with the knowledge that
you are breaking it, and why you are breaking it
Exactly so. As I've often told people, MVVM is just a tool to use. It should never become dogma - if it does that, then it's failed in it's intended purpose of making WPF/SL development easier to accomplish.
|
|
|
|
|
Pete O'Hanlon wrote: the parent ViewModel has to know what views are associated with it, and hence the ViewModels that are associated with those views. This is a real no-no.
I don't understand why you say this?
Lets say I will have a page showing a list of customers, and also the individual fields from the currently selected customer.
In MVVM I would create a VM for the page, and also (because the functionality is self-contained) a VM for the list of customers and a VM for the individual Customer fields (that is, ONE VM with properties for each Customer field)
Now, my Page VM is nonsense without having a CustomerListVM and a CustomerEditVM somehow contained within it.
It certainly doesn't know about the VIEWs but it MUST know about the ViewModels
Similarly neither the customerListVM nor the CustomerEditVM can know about the PageVM - they need to exist independently.
so surely my PageVM legitimately can say "I want to display this list of customers" - and give the list to the CustomerListVM?
|
|
|
|
|
_Maxxx_ wrote: I don't understand why you say this? Lets say I will have a page
showing a list of customers, and also the individual fields from the currently
selected customer. In MVVM I would create a VM for the page, and
also (because the functionality is self-contained) a VM for the list of
customers and a VM for the individual Customer fields (that is, ONE VM with
properties for each Customer field) Now, my Page VM is nonsense
without having a CustomerListVM and a CustomerEditVM somehow contained within
it. It certainly doesn't know about the VIEWs but it MUST know
about the ViewModels Similarly neither the customerListVM nor the
CustomerEditVM can know about the PageVM - they need to exist
independently. so surely my PageVM legitimately can say "I want to
display this list of customers" - and give the list to the CustomerListVM?
If you check out the problem that the user describes, it's not the same issue that you are describing here. What you describe is a perfectly acceptable solution where you have one view containing data derived from several VMs, where the containing VM is still being displayed.
What the OP described however was a different scenario. He has moved the implementation out of a single view into multiple views, and there is no real physical interaction between these views other than the fact that they were all originally part of one larger VM. The key point here is that the view/viewmodel interaction here is no longer with the "parent" VM, it's with the child VM. This means that, conceptually, the new VM can exist without knowledge of the old VM. The Model part, which has been entirely forgotten about in this situation, can be the same model (and is the one I would choose). So, rather than having to contort the code to worry about maintaining this disconnected list of VMs, it makes more sense to just have the child VM use the same model. Remember that a lot of people mistake the model for always being the data layer; it doesn't have to be, so a simple containing model makes this scenario a whole lot easier.
|
|
|
|
|
Thanks Pete - I was interpreting the OP differently - on re-reading after your post, I follow your logic.
cheers
|
|
|
|
|
No problems mate. It took me two readings to get what he wanted right in my head.
|
|
|
|
|
At this point I introduce my bastardisation and have 1 CustomerVM that would service all 3 of your views.
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
Mycroft Holmes wrote: 1 CustomerVM that would service all 3 of your views.
that's fine - but what if you want to use the customer lookup view elsewhere - not for editing a customer but for selecting a customer for some other function (say during order entry) You don't want to use that VM with all its overhead do you? soyou would end up with aniother ViewModel supporting the Customer lookup View...
I appreciate you call it a bastardisation - but what you're really doing is treating the containing user control as a View, with a ViewModel, and the other two as user Controls (not views) so they don't have a view model any more than a text box or combo box would. And that's fine - I just find it very confusing if you call something a View that is really just a control - and if it's not just a control, i.e. if it is a View, then it should be modelled by a ViewModel -and a ViewModel's job is to model a view (otherwise they'd be called ViewsModels)
|
|
|
|
|
Oh I'm flexible, for simple list/add dialog/detail I often have 2 views and a dialog using the same VM. If a view is particularly complex then it gets it's own VM even if that is duplicating info already in an existing VM. And no I have no intention of renaming them VsM
_Maxxx_ wrote: I just find it very confusing if you call something a View that is really just a control
The list view is the entry point into the structure, the detail view is distinct, navigated to via a double click from the datagrid on the list view, the add dialog is obviously a childwindow from the list view. All 3 use the same VM, calling the detail view a control is not correct, the dialog maybe.
Never underestimate the power of human stupidity
RAH
|
|
|
|
|