Close child window from parent viewmodel wpf mvvm - c#

Close child Window after clicking ok/cancel.
I am invoking the child window from parent mvm model:
//parent view model
var optionSetViewModel = new OptionSetViewModel();
var optionSet = new OptionSet();
optionSet.SetViewModel(optionSetViewModel);
optionSet.SetOwner(_componentview);
optionSet.ShowDialog();
The code for ok and cancel for child Window is written in child view model:
private void OkClick()
{
_childWindow.Close();
}
It closing fine but after closing when it is returing to parent view model from where it is called it is throwing null reference exception. After close I am accesing the child window values:
_someText = optionSetViewModel.SomeText;
_noteText = optionSetViewModel.NoteText;
_optionsetLanguage = optionSetViewModel.OptionSetSelectedItem;
_optionsetselected = optionSetViewModel.OptionSetSelected.ToString();

With Catel (see http://www.catelproject.com/) you can close a view based on a view model. Thus closing a view means a call like this:
myChildViewModel.CloseViewModel();
To show a child window:
var myChildViewModel = new MyChildViewModel();
uiVisualizerService.Show(myChildViewModel);

Related

Retrieve the DataContext of the Content set by using ContentSource property

I need to get the DataContext of the View set by using ContentSource property of the ModernWindow, Could you please help.I am using MVVM framework with Modern UI. The ViewModel code from where I need to show another window is as follows,
public void ShowPrompt()
{
this.PromptWindow = ObjectFactory.GetInstance<IPromptWindowViewModel>().Window as ModernWindow;
this.PromptWindow.Owner = Application.Current.MainWindow;
this.PWPMainViewModel.PromptWindowsCollection.Add(this.PromptWindow);
// Here I need to get the DataContext of PromptWindow's Content
this.PromptWindow.Show();
}
I did some debugging and found that by inherting IContent interface from ModernUI in the 'OnNavigatedTo' event
public void OnNavigatedTo(FirstFloor.ModernUI.Windows.Navigation.NavigationEventArgs e)
{
IPWPMainViewModel pwpMainViewModel = ObjectFactory.GetInstance<IPWPMainViewModel>();
pwpMainViewModel.PromptMainsCollection.Add(new ContentControl { Content = e.Content });
IPromptMainViewModel promptMainViewModel = ((UserControl)e.Content).DataContext as IPromptMainViewModel;
}
Here I am able to get the DataContext of the ModernWindow's Content i.e. of type 'IPromptMainViewModel' but here its very difficult to map/load the views into this ModernWindow as there are multiple instances of views, but I would like to do it in the ViewModel where 'ShowPrompt()' is present as there the Model will be associated with the View correctly so I can map there the views easily.
Thank you.
To get this done, I set the Content of the ModernWindow by myself (as shown in below code in a method in a ViewModel) without using the ContentSource DependencyProperty, If we use the ContentSource property it will be set for a ModernFrame type by the ModernWindow itself creating its Content instance after Navigation to that View completes in some method in ModernFrame class from ModernUI for WPF by using ModernFrame's Source DependencyProperty.
public void ShowPrompt()
{
this.PromptWindow = ObjectFactory.GetInstance<IPromptWindowViewModel>().Window as ModernWindow;
this.PromptWindow.Title = string.Concat("Control ", this.PromptOriginsEntity.PromptOriginsIdentity);
this.PromptWindow.Tag = this.PromptOriginsEntity.PromptOriginsIdentity;
this.PromptWindow.Owner = Application.Current.MainWindow;
// Store Window object in PromptWindowsCollection
this.PWPMainViewModel.PromptWindowsCollection.Add(this.PromptWindow);
this.PromptWindow.Show(); // inorder to retrieve the ModernFrame the ModernWindow is to be shown first
ModernFrame frameContent = (ModernFrame)this.PromptWindow.Template.FindName("ContentFrame", this.PromptWindow);
UserControl userControl = new UserControl { Content = GetView<IPromptViewModel>(), Tag = this.PromptOriginsEntity.PromptOriginsIdentity };
frameContent.Content = userControl;
this.PWPMainViewModel.PromptsCollection.Add(userControl);
IPromptViewModel promptViewModel = (IPromptViewModel)((IView)userControl.Content).DataContext;
promptViewModel.PromptEntity.Identity = this.PromptOriginsEntity.PromptOriginsIdentity;
}
I've uploaded a prototype app at https://wpfmvvmsamples.codeplex.com/SourceControl/latest
Thanks.

WPF Loading screen for MVVM

I am not sure where to begin with this so any help would be great. My application needs log on/loading screen. The first window will validate the user against a database then load multiple collections. Once done loading the "Log on/loading screen" closes and the actual main window appears. So this is not a true parent child relationship.
The loading of each collection is done ModelView. This is what I am trying to do, in the "Log on/loading screen";
MyViewModel _MyVM = new MyViewModel();
var newWindows = new MainWindow();
newWindows.Show();
this.Close();
The problem is figure out how to call the _MyVM in the MainWindow.
thanks for the help
You could open your LogOn view with the methode ShowDialog before the call to InitializeComponent() on your MainWindow
It seems like you're asking how to give the viewmodel to the window to be its DataContext:
MyViewModel _MyVM = new MyViewModel();
var newWindows = new MainWindow { DataContext = _MyVM };
newWindows.Show();
this.Close();

Pass value from child window back to MainPage

I have a child window in Silverlight and I wish to send a string value to populate a text box in the applications MainPage.xaml.
How can I pass the value back?
I have tried this -
MainPage m = (MainPage)Application.Current.RootVisual;
m.textBox1.Text = value;
You should do this the other way around. The parent that opens the child window should attach an event handler to an event of the child, for example:
childwindow.ButtonClicked += new EventHandler(childWindow_ButtonClicked);
Within this handler, the Parent can update its own Controls with values from properties of the child Window.
private void childWindow_ButtonClicked(object sender, EventArgs e)
{
txtValue.Text = childwindow.Value;
}
Assuming that you are using the mvvm pattern, you could use the ShowDialog method of the child window to open it.
The ShowDialog method waits until the window is closed.
After the window is closed, you can read the dependent properties from the window viewmodel and set their values in the mainpage.
var view = new ChildWindowView();
var model = new ChildWindowViewModel();
view.DataContext = model;
var result = view.ShowDialog();

InvalidOperationException raised when navigating back to a view

I've a child view (SharedView) that's shared between two parent views so I add it to each parent view through a Region like this
<StackPanel>
<ContentControl cal:RegionManager.RegionName="SharedViewRegion" />
</StackPanel>
In the parent view's ViewModel I register the child view like this
regionManager.RegisterViewWithRegion("SharedViewRegion", typeof(SharedView));
When I run the application if I open only one of the parent views it works as expected but if I open the two parent views then I get the following exception
An exception occurred while creating a region with name
'SecondRegion'. The exception was: System.InvalidOperationException:
Specified element is already the logical child of another element.
Disconnect it first.
I've been googling and this is the closer solution I found to my problem InvalidOperationException occurs when the same view instance is added to multiple ContentControl regions
But I'm using the prism navigation feature so I'm instancing the parent view like this
regionManager.RequestNavigate("ModuleRegion", new Uri("ParentView1", UriKind.Relative));
Can someone help me to solve this?
Try doing the following:
Add a name to the ContentControl that is hosting the region
Now you have to remove the region's content before leaving the parent view so in the ViewModel add the following code to the OnNavigatedFrom method
public void OnNavigatedFrom(NavigationContext navigationContext)
{
ParentView.MyContentControl.Content = null;
}
Note: You can access the parent view importing it in your ViewModel.
Now you need to add the content to the region by hand because you removed it before leaving the region. Here's the code
public void OnNavigatedTo(NavigationContext navigationContext)
{
SharedView view = (SharedView)ServiceLocator.Current.GetInstance(typeof(SharedView));
ParentView.MyContentControl.Content = view;
}
Note: In this method you must add some workaround because the first time you open this view you'll get a System.InvalidOperationException because PRISM will try to add the SharedView to MyContentControl.
Here's a possible workaround
bool isFirstTime = true;
public void OnNavigatedTo(NavigationContext navigationContext)
{
if (isFirstTime)
{
isFirstTime = false;
return;
}
SharedView view = (SharedView)ServiceLocator.Current.GetInstance(typeof(SharedView));
ParentView.MyContentControl.Content = view;
}
You have to do the same work in all parent views that share the SharedView
I hope this help you
You should directly add view to region instead of view discovery for this case. Give unique names to your parent views (you can use a counter to make up a unique name).
var region = this.regionManager.Regions["SharedViewRegion"];
var viewName = string.Format("SharedView{0}", this.countParent+1);
//Only add if it doesn't exist
var view = region.GetView(viewName);
if (null==view)
{
//Use container to get new instance of the parent view.
view = this.container.Resolve<SharedView>();
region.Add(view, name);
//Increment the counter as you added a new parent view
this.countParent++;
}
//Now activate the view
region.Activate(view);

Pass values from one to another page

How we can pass the values from a child window to the parent window in silverlight 3 by using Properties (ie Databinding).
In my work, it includes a parent window and a child window. The child window contains a text box, which returns a value after the hitting OK button it to Parent window. I already did this by using message sending and receiving events. But now i wish to change that to using properties.
Parent Window:
ChildWindow myWin = new MyWindow("Test", "Test of shared ui elemnts");
myWin.Show();
myWin.Closed += new EventHandler(myWin_Closed);
void errorWin_Closed(object sender, EventArgs e)
{
ErrorWindow wrr = (ErrorWindow)sender;
string mytext = wrr.MyText; // Can access any property that was set ChildWindow
}

Categories