Reputation: 49590
What's the right approach to open a child window (for example, to modify a selected item on the main window) keeping MVVM in mind?
Here's what I have: MainWindow.xaml (and in MainWindow.xaml.cs it assigns MainVM as its own DataContext)
I would also like to have: ChildWindow.xaml and barebones ChildWindow.xaml.cs with ChildVM behind controls.
So, now:
ChildWindow
and pass some object Data
to its
ChildVM
? MainVM
? Data
be observed
by MainVM
while they are being worked on by ChildVM
?Here's what I tried - it doesn't solve everything, but is this even the right direction?
Window
, called DialogWindow
, which has 3 DependencyProperties: Data
(for input data), ResultData
(for output data) and ResultValue
(for a bool result). ResultData
and ResultValue
are both set by the ChildVM
of DialogWindow
using Binding, and when ResultValue
is set, the DialogWindow
closes.At the moment, the ChildWindow
is launched (for all intents and purposes) from MainWindow.xaml.cs - kinda bad. I can then pass some input data, like so:
ChildDialogWindow w = new ChildDialogWindow();
w.Data = myDataObj;
So, now I need to have a property Data
on ChildVM, and set in ChildDialogWindow.xaml.cs. Again, making .xaml.cs thicker.
I thought that maybe a better approach that avoids MainWindow.xaml.cs would be some kind of DialogService
which is passed to MainVM
as a dependency. But then, how can I pass values to the ChildVM
?
Upvotes: 1
Views: 1789
Reputation: 415
I'm using the ICommand helper "RelayCommand," and pushing an IntPtr datatype to the new ViewModel (or use any other object.) Lots of cookie cutter stuff.
Main View:
<Button Command="{Binding DataContext.ShowObjectInfoCommand}" CommandParameter="{Binding ObjectOffset}" Content="{Binding Name}"/>
MainViewModel:
private RelayCommand _showObjectInfoCommand;
public RelayCommand ShowObjectInfoCommand { get { return _showObjectInfoCommand ?? (_showObjectInfoCommand = new RelayCommand(ExeShowObjectInfoCommand)); } set { } } //Draw Specific Item Table
void ExeShowObjectInfoCommand(object parameter)
{
ViewObjectInfo objInfo = new ViewObjectInfo();
IObjectOffsetParameter viewModel = objInfo.DataContext as IObjectOffsetParameter;
viewModel.ObjectOffset = (IntPtr)parameter;
objInfo.Show();
}
New ViewModel + interface:
interface IObjectOffsetParameter
{
IntPtr ObjectOffset { get; set; }
}
class ViewModelObjectInfo : ViewModelBase, IObjectOffsetParameter
{
public ViewModelObjectInfo()
{
}
private IntPtr _objectOffset; //Entity Offset
public IntPtr ObjectOffset
{
get { return _objectOffset; }
set { if (_objectOffset != value) { _objectOffset = value; RaisePropertyChanged("Offset"); } }
}
}
New View code-behind:
InitializeComponent();
ViewModelObjectInfo viewModel = new ViewModelObjectInfo();
this.DataContext = viewModel;
New View xaml:
<TextBlock Text="{Binding ObjectOffset}"/>
Upvotes: 0
Reputation: 549
Try this. Make a DialogService.cs
public class DialogService
{
public void Show(FrameworkElement view, ChildViewModel ChildVM)
{
Window window = new Window();
window.Content = view;
window.DataContext = ChildVM;
// For closing this dialog using MVVM
ChildVM.RequestClose += delegate
{
window.Close();
};
window.Show();
}
}
Now in ChildVm class, add this
public ICommand CloseCommand
{
get
{
if (_closeCommand == null)
_closeCommand = new RelayCommand(param => this.OnRequestClose());
return _closeCommand;
}
}
public event EventHandler RequestClose;
void OnRequestClose()
{
EventHandler handler = this.RequestClose;
if (handler != null)
handler(this, EventArgs.Empty);
}
Now, this the way to launch this
public void OpenChildDailog()
{
DialogService service = new DialogService();
ChildViewModel childVM = new ChildViewModel();
childVM.Data = ; // Assign whatever you want
childVM.ResultData = ;
service.Show(new ChildView(), childVM);
// Now get the values when the child dailog get closed
var retVal = childVM.ResultValue;
}
Upvotes: 1