I was wondering what the best approach is for sharing a menu across all wpf windows/views.
My Application doesnt really fit the navigation model, so will probably use a Ribbon control.
I am leaning towards creating a user control for the menu and dropping it on each view, but have also seen Josh Smith's msdn article, where he loads user controls.
Are there any other options or established best practices?
Thanks in Advance.
I ended up implementing in a way similar to Josh Smiths; I have however simplified things a bit.
All views are usercontrols, except the MainWindow.
The MainWindow contains a ContentTemplate which is bound to a property holding reference to a single UserControl in the view model.
I then have an ApplicationController responsible for controlling the view and view model lifecycle.
The ViewModel base class used by each view contains a reference to the IApplicationController.
The MainWindowViewModel then makes calls to the ApplicationController to load a new view etc.
Still not 100% on this approach so would welcome any further suggestions.
Here's what I would probably try:
Define an ISharedMenu interface
Create a UserControl which uses the ISharedMenu as its DataContext.
For each ViewModel that you want to use the shared menu, implement the ISharedMenu interface.
Related
probably a beginner question,
I develop in c # wpf a graphical application with different windows, if I now open a new window with button and there, for example, capture a customer, then how can the other window still remain interactible with the open table?
or how can I run a function in another window that is supposed to update a DataGrid of another window (other .xaml file)?
Because neither window should actually control the access or view of the underlying data, they both interact with it via a intermediary class/object.
For WPF this pattern is commonly MVVM: Model, View, ViewModel. Your WPF Windows/Forms are the Views, and the data interaction will be in the ViewModel and Model.
I've not had to learn this in a while, but LearnMVVM looks to be reasonable starting point.
I suggest you Implement a ViewModel (if youre lazy there is MVVM Lite) with public or internal access mods. Then call the specified method to update the ViewModel.
You can pass a reference from your 2nd Window to your MainWindow by passing it though the constructor if you, for some reason, cant use static constructs.
What are you looking for is MVVM-Design Pattern (or MVC):
Model − It simply holds the data and has nothing to do with any of the business logic.
ViewModel − It acts as the link/connection between the Model and View and makes stuff look pretty.
View − It simply holds the formatted data and essentially delegates everything to the Model.
Wikipedia: MVVM
Tutorialpoint: MVVM-tutorial
I have a view that I'll call View1 that has a nested user control that I'll call View2. My main application creates and shows View1 which in turn creates View2 since it is a user control on View1. Both View1 and View2 have their own viewmodels. What I need to do is get a value from View1's viewmodel to View2's viewmodel.
View2 is meant to be a completely self-contained control with its own functionality that is reusable in any other view, but it needs a piece of information from whatever view it is contained in. In the case given here, that would be View1.
My first attempt was to create a dependency property on View2 so it could be set in View1 like so:
<myUserControls:View2 MyProperty="{Binding RelativeSource={RelativeSource Self}, Path=Parent.DataContext.MyProperty}"/>
This works to set the dependency property, but that doesn't help to get the property value into View2's viewmodel where I can work with it.
I am doing this in Silverlight, if that makes any difference.
Anyone know if there is a way to do this?
I would recommend using the "Mediator" pattern, or some sort of communication between viewmodels. I personally have used galasoft MVVM light messaging to great deals of success. Rachel has also written a pretty good blog on navigation: Rachel's MVVM blog
But I would try and decrease the coupling in your program by letting the messaging handle the data context switch and viewmodel updates as opposed to creating a dependency property.
You could for instance have a baseviewmodel class which all view models inherit from, and use a polymorphic generic "view model" property which is of type baseviewmodel in your main viewmodel. Once the message was received to switch from viewmodel #1 to viewmodel #2, call a "update model" function (which you have declared in your baseviewmodel and override in your VM #2) which will then handle updating your VM #2.
I've recently been learning the MVVM pattern in WPF and just started making my first proper, rather big application. So far it's all smooth sailing, and I'm liking what I'm seeing a lot. However I recently met something of a stumbling block.
The application is built with a main TabControl, each TabItem containing a pretty big details view.
TabControl inside main View, ItemsSource bound to MainViewModel.OpenTabs
TabItem with data specific View+ViewModel
TabItem with data specific View+ViewModel
TabItem with data specific View+ViewModel
etc...
The OpenTabs collection is an ObservableCollection<BaseViewModel> on MainViewModel, and the TabControl's SelectedItem is bound to MainViewModel.ActiveTab.
So far so good! However, what I'm not sure I'm getting is how to handle closing of tabs while at the same time following MVVM. If I wasn't trying to be strict with the MVVM (in order to learn it properly), I'd just bind a MouseDown-event on the TabItem-headers and thus get a reference to the clicked item in that event, removing it from the OpenTabs collection in that way. But - unless I'm mistaken - the interaction logic shouldn't need references to actual UI items in order to be effective and proper MVVM.
So, how do I handle this MVVM style? Do I use a command that sends a specific parameter with it to my MainViewModel? It seems like the preferred implementation of ICommand in MVVM doesn't take object parameters (looking at MVVM Light as well as some other tutorials).
Should I just create a CloseTab(int id) public method on my MainViewModel and call that from the view codebehind after catching the Click on my TabItem close button? This seems like MVVM-cheating. :)
Also a final note - this should work even if I click close on a TabItem that isn't the currently active one. Otherwise it wouldn't be hard to setup with OpenTabs.Remove(ActiveTab).
Thanks for any help! I'd also appreciate any links to recommended reading/watching regarding these problems.
Solution: It seems the best way is to use a command that can accept command parameters. I used the RelayCommand from MVVM Light framework:
In MainViewModel:
CloseTabCommand = new RelayCommand<BaseViewModel>((vm) =>
{
OpenTabs.Remove(vm);
});
In XAML:
<Button
Command="{Binding Source={StaticResource MainViewModel}, Path=CloseTabCommand}"
CommandParameter="{Binding}">
Note: Your binding paths may of course vary depending on how your Views and ViewModels are set up.
The best and the right way is to create the command. In different frameworks ICommand usually has two implementation, with the parameter and without one (as often you do not need it).
MVVM light has two ICommand implementation as well: RelayCommand and RelayCommand<T>
I suggest creating your own DelegateCommand implementation, a good example on how to this can be found here or here. Or use the Prism variant, you can download it here.
With a DelegateCommand you can pass arguments down to your ViewModel.
I am required to use the mvvm pattern. I know that the viewmodel should not care about the view from what I been reading. As a result I don't know how to solve this problem:
I have a dll that basically turns a textbox and listview into an autocomplete control:
SomeDll.InitAutocomplete<string>(TextBox1, ListView1, SomeObservableCollection);
anyways I don't know how to call that method from the viewmodel using the mvvm patter. if I reference the controls in the view I will be braking the rules.
I am new to MVVM pattern and my company requires me to follow it. what will be the most appropriate way of solving this problem?
I know I will be able to solve it by passing the entire view to the viewmodel as a constructor parameter but that will totaly break the mvvm pattern just because I need to reference two controls in the view.
What you're doing here is a pure view concern, so I'd recommend doing it in the view (i.e. the code-behind). The view knows about the VM and its observable collection, so why not let the code behind make this call?
(I'd also recommend seeing if you can get a non-code/XAML API for "SomeDll", but I have no idea how much control you might have over that)
There are two things that I'd point out here -
First, this is effectively all View-layer code. As such, using code behind isn't necessarily a violation of MVVM - you're not bridging that View->ViewModel layer by including some code in the code behind, if necessary.
That being said, this is often handled more elegantly in one of two ways -
You could wrap this functionality into a new control - effectively an AutoCompleteTextBox control. This would allow you to include the "textbox" and "listview" visual elements into the control template, and bind to the completion items within Xaml.
You could turn this into an attached property (or Blend behavior), which would allow you to "attach" it to a text box, and add that functionality (all within xaml). The items collection would then become a binding on the attached property (or behavior).
Hello fellow StackOverflow users (or Stackoverflowers?):
I'm learning-by-coding WPF. I read several articles/saw several screencasts, and coming from a WEB dev background, I fired up VS2010 and started doing a sample application that would help me learn the basics.
I read some about MVVM too, and started using it. I set up my solution to use WPF 4.0, ActiveRecord 2.1 and SQLite, and everything went kind well. But I still have some doubts:
I created a MainWindowViewModel, and am using the RelayCommand class from here to... relay the command. Am I breaking any guidelines by having a MenuItem from the MainWindow to have its command bound to a property of this viewmodel?
This action I'm binding the MenuItem command to is going to instantiate a new ViewModel and a new View, and show it. Again, is that ok in the MVVM context?
My MainWindow will be a kind of "dashboard", and I will have more than one model attached to this dashboard. Should I just wrap all those models in a single view model?
Something like this:
public class MainWindowViewModel {
private ObservableCollection<Order> openOrders;
private Address deliveryAddress;
private Order newOrder;
/* Wrappers for the OpenOrders Collection */
/* Wrappers for Delivery Address */
/* Wrappers for New Order */
/* Command Bindings */
}
TIA!
I created a MainWindowViewModel, and am using the RelayCommand class from here to... relay the command. Am I breaking any guidelines by having a MenuItem from the MainWindow to have its command bound to a property of this viewmodel?
No, you're not breaking any guideline. It's perfectly appropriate to bind the MenuItem to a command of the MainWindowViewModel (where else would you put this command anyway ?)
This action I'm binding the MenuItem command to is going to instantiate a new ViewModel and a new View, and show it. Again, is that ok in the MVVM context?
It's perfectly fine to create a new ViewModel, of course. As for creating a new view, it depends on how you create it... you should of course never instantiate a view explicitly from the ViewModel, because it would introduce a dependency of the VM to the view.
My MainWindow will be a kind of "dashboard", and I will have more than one model attached to this dashboard. Should I just wrap all those models in a single view model?
It depends on what you mean by "wrap"... Your MainWindowViewModel could expose other ViewModels through properties, and theses VMs would be displayed in different parts of the view. If that's what you mean, yes, you should wrap them.
Adding to the Thomas answer:
I would create different usercontrols for each part of the dashboard and assign a viewModel to each usercontrol.
I created a MainWindowViewModel, and am using the RelayCommand class from here to... relay the command. Am I breaking any guidelines by having a MenuItem from the MainWindow to have its command bound to a property of this viewmodel?
No, that's exactly where you put commands.
This action I'm binding the MenuItem command to is going to instantiate a new ViewModel and a new View, and show it. Again, is that ok in the MVVM context?
It shouldn't need to know how to instantiate a new view; that's the view's job. The specifics of how to do this depend on how you're showing this new view - it could be as simple as having a ContentPresenter in the view that's bound to a property in the view model, so when you set the property (and raise PropertyChanged) the ContentPresenter renders the new object with its related DataTemplate.
Things get a little hinky if by "instantiate a new view" you mean "open a new window." There's not an especially elegant way to do this, especially if you want the new window to be a modal dialog. One way is to add an event handler to the view's code-behind that listens to PropertyChanged on the view model; when the subordinate view model property gets set, the code in the view creates and shows the new window.
My MainWindow will be a kind of "dashboard", and I will have more than one model attached to this dashboard. Should I just wrap all those models in a single view model?
Sure. That's a really common pattern. It's not at all uncommon, for instance, to expose an observable collection property and bind an ItemsControl of some kind to it; the view will automagically create views for every view model you put in that collection. Again, the specific implementation really depends on your application.