Question about Simple MDI example...

Topics: Conventions, UI Architecture
May 24, 2011 at 3:54 AM

Hello,

 

I am going through the examples and working on SimpleMDI. Little confused about an issue.. think it has to do with the naming conventions..

 

When the "OpenTab" button is clicked in ShellView.xaml, I see how the "OpenTab" method in the vm is called based on the name attribute matchup. Then in that method:

ActivateItem(new TabViewModel {
                DisplayName = "Tab " + count++
is run. My question is how does it know to add the new instance of "TabViewModel" to the <TabControl> named "Items" in the ShellView.xaml file?

Its not clear to me how that association is made...
Thanks
Harold


 

May 24, 2011 at 5:47 AM

Since the TabControl has the x:Name="Items" and the ShellViewModel inherits Conductor<IScreen>.Collection.OneActive CM will bind to IObservableCollection<T> Items defined in class OneActive.

 When you call ActivateItem on the conductor it will add it to the Items collection..

 

Does it make any sense for you?

May 24, 2011 at 11:53 AM

Hello and thanks for the quick response!

 

Yes, that association makes sense, but what happens if on a view there is more then 1 tab control? Since they all couldn't be named "Items", how can this automatic wiring up be done? 

 

Thanks

Harold

Coordinator
May 24, 2011 at 12:55 PM

They key is not in the specific name "Items" The key is that the ShellViewModel has an Items property and the TabControl was named with the same name. You could have any number of collections on your VM. If the items controls are named the same, their items sources will be matched up. The docs on conventions discuss a bit more how this works http://caliburnmicro.codeplex.com/wikipage?title=All%20About%20Conventions&referringTitle=Documentation

May 26, 2011 at 3:32 AM

So here is a simple change I've made using 2 tabcontrols... basically just duplicated the first tabcontrol and housed each of them in a row in a grid...

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <DockPanel Grid.Row="0">
            <Button x:Name="OpenTab"
                Content="Open Tab" 
                DockPanel.Dock="Top" />
            <TabControl x:Name="Items">
                <TabControl.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <TextBlock Text="{Binding DisplayName}" />
                            <Button Content="X"
                                cal:Message.Attach="DeactivateItem($dataContext, 'true')" />
                        </StackPanel>
                    </DataTemplate>
                </TabControl.ItemTemplate>
            </TabControl>
        </DockPanel>

        <DockPanel Grid.Row="1">
            <Button x:Name="OpenTab2"
                Content="Open Tab" 
                DockPanel.Dock="Top" />
            <TabControl x:Name="Items2">
                <TabControl.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <TextBlock Text="{Binding DisplayName}" />
                            <Button Content="X"
                                cal:Message.Attach="DeactivateItem($dataContext, 'true')" />
                        </StackPanel>
                    </DataTemplate>
                </TabControl.ItemTemplate>
            </TabControl>
        </DockPanel>
    </Grid>

and the viewmodel change:

 public class ShellViewModel : Conductor<IScreen>.Collection.OneActive
    {
        int count = 1;

        public void OpenTab()
        {
            ActivateItem(new TabViewModel{DisplayName = "Tab " + count++});
        }

        public void OpenTab2()
        {
            ActivateItem(new TabViewModel{DisplayName = "Tab " + count++});
        }
    }

I know this would not do what I want, which is to have "OpenTab2" populate the 2nd tab control and "OpenTab" populate the first one.. currently, they both populate the first one...

How does CM solve this issue? This simple example will help clarify the conventions I am sure...

Thanks

Harold

May 26, 2011 at 11:45 AM

To address your sample scenario you need two distinct conductors. They could be hosted in a parent VM holding both of them (typically as properties)