Issue with opening Child window from Main window using WPF with MVVM - c#

I am learning WPF with M-V-VM. And I am using ICommand, RelayCommand.
I have several Views, Models, and ViewModels.
The MainWIndowView open upon on application start. The MainWindowView has a button that opens another WPF window called “FileListview” via MainWindowViewModel.
The FileListView has a button “View Lookup”, which supposed to open another WPF window called “LookupView” via FileListViewModel. But I could not make this button to work unless I specify FileListView in App.xaml.cs instead of MainWIndowView. I could not understand why “View Lookup” button work if I make application to start from “FileListView” . I also don’t understand whether I need model for MainWindowView, and FileListView since I don’t have anything going except one view’s button is opening another view.
On code behind file “App.xaml.cs” I have
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
WPFProject. MainWIndowView window = new MainWIndowView ();
MainWIndowViewModel VM = new MainWIndowViewModel ();
window.DataContext = VM;
window.Show();
}
}
I would appreciate if somebody can point me to good article or sample code using WPF with M-V-VM that reflect my issue.

Here is my approach to use dialogs/child windows with mvvm and wpf. please note the comment from sllev and post all relevant code.

After rethinking the issue, I was able to figure out the solution.
The cause of the issue: I was not associating View with it’s ViewModel class.
So I put the following code in code behind of FileListView.xaml.cs.
public partial class FileListView: Window
{
private FileListViewModel _ fileListViewModel = new FileListViewModel ();
public FileListViewModel ()
{
InitializeComponent();
base.DataContext = _fileListViewModel;
}
}
Thank you

Related

How to open a new Window from an other class in C#/WPF?

So I'm still learning how to do C# applications and I have actually a problem with a window.
I've created a WPF project and I've separated some part of my main window in sub-parts (user-controls) so I can have a cleaner xaml code to work with.
I have a lot of different UserControl such as UserControlMenuStrip. All of them are inside the MainWindow.
Inside the MenuStrip was a MenuItem called Parameters :
<MenuItem Header="_Parameters" x:Name="MenuParameters"/>
I have created a new window called ParametersWindow. My goal was to open a child window centered with the main window when I click on the item.
But I don't really know how to proceed? Should I make a click= event and write down the code inside the linked UserControlMenuItem.xaml.cs linked file? Or in the MainWindow.xaml.cs file? Or maybe a new and clean file?
When I try to put it inside UserControlMenuItem.xaml.cs, I can't properly set the owner of the window I create this method but I can't set the owner:
private void OpenParametersWindow()
{
WindowParameters WinParam = new WindowParameters();
WinParam.Owner = MainWindow();
WinParam.WindowStartupLocation = WindowStartupLocation.CenterOwner;
WinParam.Show();
}
And, when I try via the MainWindow.xaml.cs I can't even get the variable...
So... How can I properly open the Window properly? And should I do it in the xaml.cs file or create a new one for a better understanding?
I've Created a class and added a static field as MainWindow to holding reference
class ReferenceClass
{
public static MainWindow mainWindow = null;//firstly null.we will set it in WindowLoaded event.
}
You can create a class like this for accessing reference of your MainWindow from wherever you want.Give your MainWindow reference to its static field.
MainWindow Loaded Event
private void Window_Loaded(object sender, RoutedEventArgs e)
{
ReferenceClass.mainWindow = this; //setting the reference to static field of ReferenceClass.
}
Menu Click (Event called on MenuStrip UserControl)
private void MenuItem_Click(object sender, RoutedEventArgs e)
{
NewWindow nw = new NewWindow();
nw.Owner = ReferenceClass.mainWindow;//Calling the reference of MainWindow from our class.
nw.WindowStartupLocation = WindowStartupLocation.CenterOwner;
nw.Show();
}
Here we go
Project
This is just a way for solving this issue.We can find more solutions which are better than mine but i use this solution when i need.
A handle to the parent window for any usercontrol can be obtained that way:
Window wndParent = System.Windows.Window.GetWindow(this);
WinParam.Show(wndParent);
But when working with WPF, it is more convenient to use the MVVM pattern
As you writing UI in WPF it is preferred to implement it with MVVM pattern. It allows you to have a clear separation of concerns between code and presentation.
Regarding your question about how to set Owner I suggest reading this series of articles about dialogs in WPF implemented with MVVM in mind
https://www.c-sharpcorner.com/article/dialogs-in-wpf-mvvm/

Making a new WPF window from C# class

I currently have one window designed in WPF and coded in C#. I want one of my buttons to open another window, which I would also like to design in WPF. What is the best way for me to do this? Can I make multiple xaml files and call them from the same .cs class? Or should I just have one xaml file? I tried to add a new window into my xaml but it won't allow me to do that. I want all the code to be in the same C# class.
Yes, you can have multiple XAML files and call them from the same .cs file.
For exemple, let's say you have Window1.xaml and Window2.xaml. Window1 is your main window, and the code behind will look like this :
public partial class Window1 : Window
{
public MainWindow()
{
InitializeComponent();
}
}
In Window1 you have a button named btnOpenWindow. On click, you may do that to open Window2 :
private void btnOpenWindow_Click(object sender, RoutedEventArgs e)
{
var window = new Window2();
window.Show();
}
Then a new Window2 is opened.
However you won't be able to get events or others things coming from Window2 in Window1.xaml.cs, obviously you will control that in Window2.xaml.cs for exemple.
You should use the MVVM pattern in your project.
So you have different windows and just one ViewModel to handel these views and your data.
Have a look on: MVVM: Tutorial from start to finish?

WPF & MVVM - Close Window from within Child control

I need to close a modal window from a ViewModel based on a click command that is triggered in a control that is presented within the window.
So, I have MainViewModel, JimViewModel, JimWindow and JimControl. MainViewModel creates a JimWindow and sets its DataContext to JimViewModel. JimWindow contains JimControl, which contains a button. When this button is clicked, I'd like to trigger a command that somehow closes JimWindow.
I've seen a few questions that answer this with respect to closing the Window from the actual Window (By passing the instance of the Window to a Command on the ViewModel), but it doesn't translate to what I want to do.
I'm not using a framework so I have no handy messenger to assist me. Can anyone help? Is it a case of somehow referencing the Name of the parent window from the control?
MainViewModel should not be creating windows, at least not directly. VMs should only create VMs. A window is part of the view world.
If you need your JimVM hosted in a window, then it would be better to have some kind of WindowService abstracted away behind an interface. MainVM then just creates JimVM and gives it to the window service to host in a window
Once you've got the windows bit decoupled into a separate service, then you can do all your crufty window stuff in there. I would have JimVM expose a CloseCommand and a Closed event. You can bind your JimControl button to the CloseCommand, and the windows service can subscribe to the Close event, and tear down the window when it fires.
This keeps the view and VM stuff completely separate. The only thing that knows how to glue the two together is the window manager.
Although idea of ViewModel creating a View sounds a little backwards, you could use messaging, e.g. TinyMessenger or Messenger that comes with MVVMLight.
You could then register for a message in your View/ViewModel and send it from-anywhere. A really simplistic example using MVVMLight could be:
// custom message
public class CloseMessage : MessageBase
{
public CloseMessage(object sender)
:base(sender)
{}
}
// main view registers for a message
public partial class MainWindow : Window
{
public MainWindow()
{
Messenger.Default.Register<CloseMessage>(this, message =>
{
// do teh stuff
});
}
...
}
// command bound to close button sends the message
private void YourCloseMainViewCommand()
{
Messenger.Default.Send(new CloseMessage(this));
}

How to manage multiple windows in MVVM

I am aware there are a couple of questions similar to this one, however I have not quite been able to find a definitive answer. I'm trying to dive in with MVVM, and keep things as pure as possible, but not sure how exactly to go about launching/closing windows while sticking to the pattern.
My original thinking was data bound commands to the ViewModel triggering code to start a new View, with the View's DataContext then set to it's ViewModel via XAML. But this violates pure MVVM I think...
After some googling/reading answers I came across the concept of a WindowManager (like in CaliburnMicro), now if I was to implement one of these in a vanilla MVVM project, does this go in with my ViewModels? or just in the core of my application? I'm currently separating out my project into a Model assembly/project, ViewModel assembly/project and View assembly/project. Should this go into a different, "Core" assembly?
Which leads on a bit to my next question (relates somewhat to the above), how do I launch my application from an MVVM point of view? Initially I would launch my MainView.xaml from App.xaml, and the DataContext in the XAML would attach the assigned ViewModel. If I add a WindowManager, is this the first thing that is launched by my Application? Do I do this from the code behind of App.xaml.cs?
Well it mainly depends on how your application looks like (i.e. how many windows opened at the same time, modal windows or not...etc).
A general recommendation I would give is to not try to do "pure" MVVM ; I often read things like "there should be ZERO code-behind"...etc., I disagree.
I'm currently separating out my project into a Model assembly/project,
ViewModel assembly/project and View assembly/project. Should this go
into a different, "Core" assembly?
Separating views and ViewModels into different assemblies is the best thing you can do to ensure you won't ever reference something related to the views in your viewModel. You'll be fine with this strong separation.
Separating Model from ViewModel using two different assemblies could be a good idea too, but it depends on what your model looks like. I personally like 3-tier architectures, so generally my model is the WCF client proxies and are indeed stored in their own assembly.
A "Core" assembly is always a good idea anyway (IMHO), but only to expose basic utility methods that can be used in all the layers of your application (such as basic extension methods....etc.).
Now for your questions about views (how to show them...etc), I would say do simple. Personally I like instantiating my ViewModels in the code-behind of my Views. I also often use events in my ViewModels so the associated view is notified it should open another view for example.
For example, the scenario you have a MainWindow that should shows a child window when the user click on a button:
// Main viewModel
public MainViewModel : ViewModelBase
{
...
// EventArgs<T> inherits from EventArgs and contains a EventArgsData property containing the T instance
public event EventHandler<EventArgs<MyPopupViewModel>> ConfirmationRequested;
...
// Called when ICommand is executed thanks to RelayCommands
public void DoSomething()
{
if (this.ConfirmationRequested != null)
{
var vm = new MyPopupViewModel
{
// Initializes property of "child" viewmodel depending
// on the current viewModel state
};
this.ConfirmationRequested(this, new EventArgs<MyPopupViewModel>(vm));
}
}
}
...
// Main View
public partial class MainWindow : Window
{
public public MainWindow()
{
this.InitializeComponent();
// Instantiates the viewModel here
this.ViewModel = new MainViewModel();
// Attaches event handlers
this.ViewModel.ConfirmationRequested += (sender, e) =>
{
// Shows the child Window here
// Pass the viewModel in the constructor of the Window
var myPopup = new PopupWindow(e.EventArgsData);
myPopup.Show();
};
}
public MainViewModel ViewModel { get; private set; }
}
// App.xaml, starts MainWindow by setting the StartupUri
<Application x:Class="XXX.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
...
StartupUri="Views/MainWindow.xaml">

WPF MVVM Get Parent from VIEW MODEL

In a MVVM WPF application.
How do you set a second windows parent from the ViewModel?
example:
view1 -- viewModel1
viewModel1's command calls:
var view2 = new view2
view2.Owner = <----This is the problem area. How do I get view1 as the owner here from the viewModel?
view2.Show()
EDIT:
See accepted answer below, then read the following edit.
I'am using MVVM light -> http://mvvmlight.codeplex.com/ (awesome btw)
The baked-in messaging system is great. I am now sending a message from the viewmodel to my view telling it to show another window.
For the message I'am currently using a string with a switch statement in the main view to determine what view to open; however I may tinker with the tokens that also are part of MVVM light toolkit.
Thank you!
In my opinion, opening a new window is the responsibility of the View, not of the ViewModel. Personally, I would use the same approach as used for displaying a dialog box (this was discussed in this forum already):
Have the ViewModel send a Message to the View requesting that it opens a new Window.
(alternatively) use an IDialogService or whatever you want to call it which you pass to the ViewModel's constructor. This service will be in charge of opening the Window (or of delegating this task to the View).
This way, you keep a clean separation of concerns and your VM remains testable (you can unit test that the request to open the new WIndow has been sent, but you couldn't test that the window has been, indeed, open).
Does that make sense?
Cheers,
Laurent
From your viewmodel call
Messenger.Default.Send<NotificationMessage>(new NotificationMessage("Open Window"));
And from your view's codebehind (a view that call the second
view) easily write this in the constructor:
Messenger.Default.Register<NotificationMessage>(this, ReplyToMessage);
And also write this method in the view's codebehind:
private void ReplyToMessage(NotificationMessage msg)
{
if (msg.Notification == "Open Window")
{
SecondWindow win = new SecondWindow();
win.ShowDialog();
}
}
I don't have an answer of my own but here's a few links to things I've been looking at lately that might help. I'll also be interested in anything others suggest.
As I understand it, the key thing is, you shouldn't be creating Views from within a View Model if possible, so you need a means of communicating what you need in a loosely coupled fashion.
http://www.codeproject.com/KB/WPF/XAMLDialog.aspx
http://www.codeproject.com/KB/architecture/MVVM_Dialogs.aspx
Handling Dialogs in WPF with MVVM
You can do in this way like you need to create some events and register those in view and call these in view model.and open that pop up window.
Like This example
public class Mainclass : MainView
{
public delegate abc RegisterPopUp(abc A);
public RegisterPopUp POpUpEvent;
public RelayCommand ShowCommand { private set; get; }
public void ShowCommand()
{
ShowCommand("Your parameter");
}
}
inside the view
MainView mn = new MainView();
Register the event here like mn.POpUpEvent += then click on tab button double time and in registers popup method write the code for opening the pop up window.
Prism-Event Aggrigator is good approach, where we can create independent module without dependency. first viewmodel will publish event and then another view or view or viewmodel can subscribe that event from event aggrigator.
in this case Unity container can also use to inject one viewmodel in to another with dependency injection.

Categories