I am new to MVVM and can't find how to do the following:
I have MainPage.xaml and ElementOnePage.xaml
When somebody double tap an element of the main page, I want to display the ElementOnePage.
MainPage display a list, ElementOnePage display the detail
My MainPage DataContext is of type ElementViewModel
1) Should my ElementOnePage DataContext also be the same ?
2) I am using QueryString parameters to pass the information about which element has been selected.
However when I retrieve the element in the OnNavigatedTo(NavigationEventArgs args) function, this is too late.
I tried defining the DataContext of the page in this method, but it didn't work.
So how can I have a page that do the expected behavior while using effectively data binding ?
I have used MVVMLight for my WP7 apps. MVVMLight uses behaviors for command binding.
Create a RelayCommand in your MainPageViewModel, call it say NavigateToElementOneCommand.
Create a EventToCommand behavior on the ListBox, and bind it to the NavigatToElementOneCommand.
(Assuming that MainPageViewModel is set as MainPage's DataContext).
In NavigateToElementCommand, write the code to navigate to the ElementOnePage.XAML.
Related
So I am doing my first WPF MVVM app. Just learning the right principle of MVVM, but there are some things that I don't understand ...
I already have several user controls defined.
First question is what is better to use, UserControl or DataTemplates to change content of the MainWindow?
And how to make "Binding" in the "MainWindow.xaml" to change UserControl/DataTemplates when button is pressed?
For example, When "next" button is pressed then contents of main window disappear and content of user control comes on the screen of "MainWindow.xaml".
Maybe with "" binding, to disable it and enable it?
I found some example which function on DataTemplate A Simple MVVM Example. It helped me to implement some things, but I see some discussions over "UserControl" vs. "DataTemplate" and how to do it? So now I am confused :)
I recently made a WPF application with the MVVM pattern, and I did the following:
I have one 'Window', the mainwindow, and in this window all UserControls are loaded.
Every UserControl has a different Viewmodel, for examples a "GeneralSettingsUserControl" has a GeneralSettingsViewModel for validation and databinding.
Every UserControl has its own codebehind where data is bound to its ViewModel
The following code I found on the internet (I don't know the url anymore) but for me it did the trick to change de ContentControl in the mainwindow.
Switcher.cs:
public static mainWindow mainWindow;
public static void switchPage(UserControl p_objNewPage)
{
mainWindow.navigate(p_objNewPage);
}
mainWindow.xaml.cs
public void navigate(UserControl nextPage)
{
PageContent.Children.Clear();
PageContent.Children.Add(nextPage);
PageContent.LastChildFill = true;
}
PageContent is the name of the Grid where the main content is located. In every UserControl you can call the Switcher.switchPage(new UserControl) to change the content of the window. So when you click a button you can call this method.
Hope it helps and good luck.
I'm building a pos system that has a main ContentControl to display different screens of the application. I use DataTemplates to map my viewmodels to views. To navigate between the different views displayed in the ContentControl I'd like to store a screenshot of the UserControl in the viewmodel when the UserControl is unloaded (or the ContentControl changes).
I posted a related question here WPF Binding FrameworkElement event to command in which I attempted to bind a command to FrameworkElement.Unloaded but that doesn't work (see answer at that link)
Is this possible without breaking the MVVM pattern?
here is a nice link to how to do a screenshot in wpf.
here is what i would do:
my mainviewmodel which handle the navigation should expose an event and raise this event before you set the new contentviewmodel. the old contentviewmodel should be in the eventargs. in your mainwindow codebehind you subscribe to the event(not breaking mvvm here). when ever this event is raise you can call the screenshot method and put the result to the oldviewmodel.
edit:
mainwindow codebehind
void NavigationChangingEvent(object sender, NavChangingArgs args)
{
var oldvm = args.ChangingViewmodel;
oldvm.Screenshoot = this.mycontentcontrolwheremyviewmodelareshown.GetJpgImage(1, 90);
}
I am trying to use MVVM light to achieve something like this. I have the following scenario:
In my Model--I have set the properties like ActivityName,Image and there is a class constructor whose is accepting 2 parameters like name and image.
Im my DataAccess--I have set the database connection and implement the required method who will fetch the data from DB and I am storing in the List and returning the list to ViewModel.
In my ViewModel--I have created the list property who will return the list by calling the GetActivities() method that I have defined in the DataAccess.
Now my problem is I am not getting how to bind it in the View so that by clicking on a button it will display the list of activities with image. By clicking on some button a new window should open with the desired result. How to bind the above list and implement the button functionality using MVVM light.
Kindly help?
Thanks
First of all, use an ObservableCollection instead of a List as it would notify the view when property or collection changes.
Then set the DataContext of your view to the viewmodel. If you use MVVMLight View Class, then the DataContext would be automatically set. You've to just give the ViewModel Name there.
Then set the ItemsSource of the DataGrid like this <dg:DataGrid ItemsSource="{Binding YourListInViewModel}"/>
For handling click event you can use the Event-To-Command behaviour and write your logics in the Button's corresponding Command handler.
Bind to DataContext of the control
I can use data binding to set the initial Content of a WPF Frame, but subsequent changes to the the bound property (implemented using INotifyPropertyChange) do not seem to change the content.
Also, does anyone know if binding directly to the Content property in this way will cause the bound item to appear in the Frame or NavigationWindow's journal?
Some context: I realize that I should probably be using the NavigationService to interact with the Frame, but I'm attempting to follow the MVVM pattern. It seems like it would be much simpler to databind to the Content property...
You can use data binding against a Frame, but you need to make sure the Mode for your Binding is set to TwoWay.
XAML:
<Frame Content={Binding Path=MyProperty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged} />
View Model:
public class MyViewModel : INotifyPropertyChanging, INotifyPropertyChanged
{
public Page MyProperty
{
get
{
return _viewModelPage;
}
set
{
this.OnPropertyChanging("MyProperty");
_viewModelPage = value;
this.OnPropertyChanged("MyProperty");
}
}
}
Many in the WPF community agree that the built-in navigation framework is broken. However, even if you were to use it, binding the Content property is not the correct approach. If you want to use MVVM with navigation you should combine it with the FrontController pattern where the ViewModel dispatches a navigation request to a Controller which then resolves that request for you. There aren't many examples of this concept available because (as I mentioned before) many developers pass on using WPF's built-in navigation.
If you want to look at a very robust navigation engine for WPF, look at nRoute It is a port of the MVC routing engine to WPF.
The Frame is a navigation host, so it is more correct to use the NavigationService to navigate to different content. If you use the INotifyPropertyChange, I suppose that you call the related event whenever the content is changed. Then, I also suppose that there is no difficult to use the NavigationService instead.
I ran into this issue a few days ago. I had a main window with a frame, and I loaded different pages into the frame (by using Navigate()). The pages' data bindings were broken, the data did not show up on the loaded page.
To repair the bindings, create or give your existing DataContext to the page inside the frame, and the bindings will work again.
I have legacy windows forms user control that exposses several public methods. I wrapped this control on a wpf user control and encapsulated the Methods with a relaycommand on the new wpf usercontrol.
Now my problem is how to use the mvvm pattern to execute the commands on my user control form the viewmodel that is used with the view hosting the new wpf usercontrol.
In viewmodel you have to add a field say
Public ICommand CommandOne
Now this command will create a new RelayCommand object depending upon your requirements/conditions.
Now, you can bind this 'CommandOne' command with any object say button on your control form.
So, whenever the button is clicked then the RelayCommand object will be created and it will execute the action given to it as a parameter.
Hope it works for you.
I Fond out how to get this to work with bindings. Need to set the mode to OneWayToSource to get the command from the user control. The tricky part is that the initialization of the command has to be done inside the loaded event of the usercontrol. If you try to do it inside of the constructor, you will end up with the default initialization from the binding which could be null.
Use PRISM EventAggregator? You can fireoff an event from ViewModel, from your Usercontrol subscribe to it.
http://www.codeproject.com/Articles/355473/Prism-EventAggregator-Sample
https://msdn.microsoft.com/en-us/library/ff921122.aspx