Question

I'm rewriting a project in WPF using Caliburn framework. I came from C++ world, so have some difficulties figuring out even simplest things...

So, let's say I have: MainView, MainViewModel, DialogView, DialogViewModel.

In MainView.xaml: ...

<MenuItem Name="Dialog" Header="Dialog"></MenuItem>

... Caliburn bounds it to a method in MainViewModel:

public void Dialog()
        {
            dynamic settings = new ExpandoObject();
            settings.WindowStartupLocation = WindowStartupLocation.Manual;
            _windowManager.ShowWindow(new DialogViewModel(_windowManager), null, settings);
        }

It works fine, Dialog pops up.

Now, in this dialog I have:

<TextBox Name="Dimension1"/>
<TextBox Name="Dimension2"/>

plus, other textboxes, checkboxes etc. Then there are OK and Cancel buttons:

<Button Content="OK" Name="OK"></Button>
<Button Content="Cancel" Name "Cancel"></Button> 

Now, as it is right now they are bound to OK() and Cancel() methods in DialogViewModel and I cannot figure out or find information on how to deal with them in DialogViewModel.
I found an example when DialogResultsAction class is created, I can bound my OK/Cancel buttons with the methods in this class, but can't understand how to proceed further...

Can you advice me what direction should I go?

Was it helpful?

Solution

I'm not sure if this is what you're looking for but you can treat the DialogViewModel like any other screen. In this example Ok and Cancel get bound to the respective methods. Technically you could set x:Name="TryClose" for the cancel button's name but I named it Cancel for this example.

In the Open method in ShellViewModel you can preset values on the dialog before you display it. And after the result is returned since you have a reference to it you can also read those values.

Open method in ShellViewModel:

 public void Open()
    {
        var dialogViewModel = IoC.Get<DialogViewModel>();
        dialogViewModel.Dimension1 = "123";
        dialogViewModel.Dimension2 = "456";
        var result = WindowManager.ShowDialog(dialogViewModel);
        if (dialogViewModel.MyDialogResult == DialogResult.OK) return;

        //do stuff with results            
        var dim1 = dialogViewModel.Dimension1;
    }

DialogView:

<Grid>
        <StackPanel>
            <TextBlock x:Name="Dimension1" />
            <TextBlock x:Name="Dimension2" />
        </StackPanel>
        <StackPanel Height="50"
                    Orientation="Horizontal">
            <Button x:Name="Ok"
                    Content="Ok" />
            <Button x:Name="Cancel"
                    Content="cancel" />
        </StackPanel>
    </Grid>

DialogViewmodel:

[Export(typeof (DialogViewModel))]
public class DialogViewModel : Screen
{
    private string _dimension1;
    public string Dimension1
    {
        get { return _dimension1; }
        set
        {
            _dimension1 = value;
            NotifyOfPropertyChange(() => Dimension1);
        }
    }

    private string _dimension2;
    public string Dimension2
    {
        get { return _dimension2; }
        set
        {
            _dimension2 = value;
            NotifyOfPropertyChange(() => Dimension2);
        }
    }

    public void Ok()
    {
        //Do stuff
        MyDialogResult = DialogResult.OK;
        TryClose();
    }

    public void Cancel()
    {
        MyDialogResult = DialogResult.Cancel;
        TryClose();        
    }
}

OTHER TIPS

If your ViewModel is based off of IScreen, use Close in the Ok or Cancel method. If you need to return a result, I'd suggest using the IEventAggregator to push the result back to the parent. If you really need to, you can use GetView() to get the view associated with the viewmodel, cast it to the right type, and set the result (assuming the view has a result, I've not used the Dialog class).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top