Pass data to Child Window in Silverlight 4 using MVVM

Archie picture Archie · May 21, 2010 · Viewed 8.8k times · Source

I have a datagrid with master detail implementation as follows:

<data:DataGrid x:Name="dgData"  Width="600" ItemsSource="{Binding Path=ItemCollection}"
                       HorizontalScrollBarVisibility="Hidden" CanUserSortColumns="False" RowDetailsVisibilityChanged="dgData_RowDetailsVisibilityChanged">
                    <data:DataGrid.Columns>
                        <data:DataGridTextColumn Header="Item" Width="*" Binding="{Binding Item,Mode=TwoWay}"/>
                        <data:DataGridTextColumn Header="Company" Width="*" Binding="{Binding Company,Mode=TwoWay}"/>

                    </data:DataGrid.Columns>
                    <data:DataGrid.RowDetailsTemplate>
                        <DataTemplate>
                            <data:DataGrid x:Name="dgrdRowDetail" Width="400" AutoGenerateColumns="False" HorizontalAlignment="Center" 
                                       HorizontalScrollBarVisibility="Hidden" Grid.Row="1">
                                <data:DataGrid.Columns>
                                    <data:DataGridTextColumn Header="Date" Width="*" Binding="{Binding Date,Mode=TwoWay}"/>
                                    <data:DataGridTextColumn Header="Price" Width="*" Binding="{Binding Price, Mode=TwoWay}"/>
                                    <data:DataGridTemplateColumn>
                                        <data:DataGridTemplateColumn.CellTemplate>
                                            <DataTemplate>
                                                <Button Content="Show More Details" Click="buttonShowDetail_Click"></Button>
                                            </DataTemplate>
                                        </data:DataGridTemplateColumn.CellTemplate>
                                    </data:DataGridTemplateColumn>
                                </data:DataGrid.Columns>
                            </data:DataGrid>
                        </DataTemplate>
                    </data:DataGrid.RowDetailsTemplate>
                </data:DataGrid>

I want to open a Child window in clicking the button which shows more details about the product.

I'm using MVVM pattern. My Model contains a method which takes the Item name as input and returns the Details data.

My problem is how should I pass the Item to ViewModel which will get the Details data from Model? And where should I open the new Child Window? In View or ViewModel?

Answer

Chazmanian picture Chazmanian · Jun 15, 2010

Opening the child window from a view model violates the separation between view and view model that the pattern is supposed to be all about. So, you probably don't have much choice about where you open the child window from - the code behind for the page that the grid is on. (And that violates the pattern as well, but, short of a complicated solution, it's about all you can do.) I use the MVVM pattern, but I'm not "religious" about it. I will violate some precepts of the pattern when efficiency dictates.

As far as passing the item to the ViewModel - I suppose you can create a property on the ViewModel that represents an id for the item. I've been using child windows as data entry forms for update and add. I tend to create a ViewModel for each one of them. In your case, you would have a ViewModel that represents the details of the item. There would be some sort of ID related to the item and details. That would be a public property on the ViewModel. You could create a constructor for the child window that takes that ID as a parameter. Then, the child window constructor could create the ViewModel and send it the ID.

Something like this - where DomainEdit is the name of the child window.

    public DomainEdit()
    {
        InitializeComponent();

        devm = new DomainEditVM();
        DataContext = devm;
    }

    public DomainEdit(Guid domainId) : this()
    {
        devm.DomainId = domainId;
        devm.GetDomain();
        txtTitle.Text = "Edit Domain";
    }

Then, from code behind where the button click for the grid occurs, you create the child window with the new constructor, passing the id that you get from the item binding in the grid row, and an independent view model for the child window takes over.

At least, that is what has been working for me.