New Dev
New Dev

Reputation: 49590

Passing complex object to a Child Window

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:

  1. How can I popup ChildWindow and pass some object Data to its ChildVM?
  2. Get the result (true/false) and result data (some complex object) back to MainVM?
  3. As a bonus, can changes in 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?

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

Answers (2)

Logan Klenner
Logan Klenner

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

UsmanAzam
UsmanAzam

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

Related Questions