I have a parent view which shows a grid. In one of the columns there is a button on every row to show a child dialog to edit the object that each row of the grid is bound to. The button is bound to a command on the view model which shows the dialog. I use CommandParameter="{Binding}" to pass a reference to object to edit to the view model of the child dialog.
I want to the dialog to be centered relative to the window it opened from which I can do with dialog.WindowStartupLocation = WindowStartupLocation.CenterOwner but I need a reference to the parent window.
I can think of two solutions but I don't think either of them is clean.
If I wasn't using the command parameter already I could pass the window to parent view model like this CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}". I could use a multi binding and a converter to pass two parameters but is this good practice? I tend to think the view model shouldn't know any thing about views.
I can pass a reference to the parent window that host the parent view to it's view model in the view model's constructor. Again what I don't like is that the view model knows about windows which seems like a dependency in the wrong direction.
What I also don't like about either of these approaches is the parent view model needs to have knowledge of the child window it is creating.
I sawthis answer which shows how to use a service that the view model can use to open a window without having any knowledge of the window its creating which is great but I kind think of a clean way to pass the parent window without going through the view model.
Related
I'm using WPF/Prism and have a Shell with toolbar in it and a region with a view in it (The view lives in another module). The view has a treeview in it that is bound to a list of view models.
I have a toolbar button in the Shell I want to have delete the selected treeview item that is in the child region/view.
What is the best way to do this?
I thought about using a command but I'm not sure if there is a way to bind the toolbar button command that lives in the Shell to the view model in the child view (that contains the tree view). Is this possible/the best way to do this?
The alternatives like using event aggregator to publish the selected item seem plausible or some type of service to publish the selected treeview item to also seem possible.
Thanks.
You could define a static CompositeCommand in a static class as part of an infrastructure project/dll. Set the toolbar button command property to this command using {x:Static}, and in the viewmodel of the view containing the TreeView you define a local DelegateCommand that you register with the CompositeCommand.
But if the button in the toolbar only applies to this particular view from the module, it would make sense to also define the toolbar as a Prism region and insert the button as a view from the module.
I'm developing a WPF C# app where I have a tree view control and if the user clicks on a node in the tree, a node-specific detail 'form' appears in a named Grid somewhere else in the form. If you click on a different node in the tree, the displayed detail form checks if the contents are saved, is dismissed, and a new detail form appears in it's place.
What I need is some starting advice. Can I still implement the forms as standalone xaml, then put some some of 'container' in the grid that I throw the form into as a child? Or just add the form as a grid child somehow. How do I programmatically load the form I want in the grid and communicate with it?
Thanks for any assistance!
Corey.
Use an event aggregator design pattern, see here for details:
http://martinfowler.com/eaaDev/EventAggregator.html
You can then have some other code which listens for the node change clicks via the event aggregator and response accordingly. This will decouple your code and make it more testable.
Am assuming you are using mvvm?
If not read up on it - will make it easier.
then you have your form with the treeview on it, bound to its itemsource on the view model.
Usually an items control like a treeview will have a selecteditem property on it.
Bind that to a property on your viewmodel which is of the type of objects contained in your treeview. Call this for example CurrentlySelectedItem.
Your details 'form' can be a control or whatever you want on the same form.
Now depending on how complete your object is - you have at least two options. If your object in the treeview has all the data you need already, then just bind the details to CurrentlySelectedItem.
Obviously it must implement INotifyPropertyChanged to tell the binding system to update the values.
If the object doesn't have enough info, then on the setter of CurrentlySelectedItem you can then fire a method to load the full object and then bind the details to that full object.
Alternativley, another popular approach, you could have the details form as a self contained control that subscribes to a message and when it recieves the message with the key of the treeview object, it loads the required info.
I have a window called MAINWINDOW that has a toolbar and a frame. Inside the frame is shown a Page called HOMEPAGE. This page has a treeview where menu options are shown. When the user clicks a node, the corresponding form (a Page) is shown inside a border in HOMEPAGE, using the Border.Content property. I have a button in the toolbar to search for customers and I need to bind this button's command property to a command which is defined inside the Customers page's viewmodel. This page is a child of the HOMEPAGE which in turn is a child of MAINWINDOW. Can you suggest a way to do this, that is to access a command defined in a child's child object?
Thank you.
That goes against the principles of MVVM.
ViewModels (and their corresponding Commands) are 1:1 to Views. Each ViewModel serves one View, and one View ONLY. It helps to think of the ViewModel as the codeBehind of the View, only that it can never access the View directly (thus it's completely decoupled from it).
Violating this principle (V to VM == 1:1), creates dependencies between ViewModels or between Views, which is a bad thing. It makes your application harder to maintain since each "module" is dependent on the implementation of other "modules".
What you should do is expose another Command on the ViewModel that serves the relevant View. That Command in turn could trigger what ever you want.
I am working on Silverlight project.
I added a custom user control (Say, control1) which has a text box and button to a xaml page (Say, Page1).
Now what I want to do is when users clicks on the button, i want to pass the value in the textbox to Page1 and do something.
So basically, I am looking for a way to pass back a value from child to parent page in Silverlight.
Thank you.
You should look into the Model View ViewModel (MVVM) pattern. It works very well with WPF and Silverlight.
http://en.wikipedia.org/wiki/Model_View_ViewModel
http://karlshifflett.wordpress.com/mvvm/ (lots of good information and demos)
You can do this through binding. Bind the Text value of the TextBox to a string property in your ViewModel and use that property throughout the code.
All the controls within your user control are accessible within your main page. If possible, write the click event of the button within the main page and you'll be able to access any control's property. Hope that work for you.
I have senario in which one view and view has binding with multiple ViewModel.
Eg. One View displaying Phone Detail and ViewModel as per bellow:
Phone basic features- PhoneViewModel,
Phone Price Detail- PhoneSubscriptionViewModel,
Phone Accessories- PhoneAccessoryViewModel
For general properties- PhoneDetailViewModel
I have placed View's general properties to PhoneViewModel.Now senario is like this:
By default View displays Phone Basic feaures which is bind with ObservationCollection of PhoneViewModel. My view have button - 'View Accessories', onclick of this button one popup screen- in my design I have display/hide Grid and bind it with ObservationCollection of PhoneAccessoryViewModel.
Now problem begins- Accessory List also have button 'View Detail' onclick I have to open one popup screen, here also I had placed one Grid and Visible/Hide it. I have bind 'ViewAccessoryDetailCommand' command to 'View Detail' button. And on command execution one function fires and set property which Visible the Popup screen.
Using such programming command fires, function calls but the property change not raises and so my view does not display popup.
Summary:
One View--> ViewModel1-->Grid Bind view ViewModel2 -->Grid Have Button and Onclick display new Grid which binded with ViewModel3-this Command fires but property not raises.
I think there is some problem in my methodology, Please, give your suggetions.
I'm not sure I completely follow what you are trying to ask, but I'll have a go at answering.
I posted an answer to (possibly) a similar question yesterday.
See
Query on MVVM pattern in WPF?
and
MVVM - what is the ideal way for usercontrols to talk to each other
I'm not sure if it does, but I hope this helps.
In WPF a View is connected to a ViewModel by setting the DataContext of the View to the ViewModel.
Since each control can only have one DataContext a View can only have one ViewModel.