Chirdeep Tomar
Chirdeep Tomar

Reputation: 4461

Binding on nested user control is not working in Caliburn Micro

I have a usercontrol(X) that gets loaded in the shell, I am using Screen/Conductors. Control X has a tabcontrol that I am trying to load with another usercontrol(Y) as a TabItem. Both the controls have their on ViewModels that do not share anything yet.

Usercontrol X:

[Export(typeof(IShell))]
public class CategoryViewModel : Screen, IShell
{}

Xaml in Control X:

<TabItem Header="Award Images">
    <StackPanel>
        <Views:ImageView cal:Bind.Model="{Binding}" />
    </StackPanel>
</TabItem>

Usercontrol Y:

[Export(typeof(IShell))]
public class ImageViewModel : PropertyChangedBase, IShell
{}

When I run the application I get the CategoryView loaded in the shell and working fine. ImageView gets loaded but none of the functionality is available.

I am expecting to see some dummy data that I am putting in the ListView on ImageView through the constructor of ImageViewModel.

Any help will be much appreciated.

Thanks.

UPDATE: CategoryView.xaml

<UserControl x:Name="CategoryViewUserControl" 
         x:Class="Central.BusinessObjects.Wpf.Views.CategoryView" 
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
         xmlns:extToolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit/extended" 
         xmlns:cal="clr-namespace:Caliburn.Micro;assembly=Caliburn.Micro" 
         xmlns:Views="clr-namespace:Central.BusinessObjects.Wpf.Views" 
         xmlns:Converters="clr-namespace:Central.BusinessObjects.Wpf.Converters" MinHeight="500" MinWidth="500">
<UserControl.Resources>
    <ResourceDictionary>            
        <Converters:CategoryTypeConverter x:Key="CategoryTypeConverter" />
    </ResourceDictionary>
</UserControl.Resources>
<StackPanel>
    <ToolBar>
        <Button Height="23" Width="75" cal:Message.Attach="SaveCategories($dataContext)">
            <StackPanel Orientation="Horizontal">
                <Image />
                <TextBlock Text="Save" />
            </StackPanel>
        </Button>           
    </ToolBar>
    <StackPanel Orientation="Horizontal">
        <ComboBox x:Name="Types" 
                  IsEditable="True" 
                  Background="Beige" 
                  IsReadOnly="True" 
                  Text="Select Award Type" 
                  DisplayMemberPath="Description"                     
                  Height="23" Width="219" />

        <ComboBox x:Name="Awards" 
                  DisplayMemberPath="Year" 
                  Background="Beige"                      
                  Height="23" Width="120" />
        <Label Content="Image" />
        <TextBlock x:Name="AwardImage" TextAlignment="Justify" MinWidth="300" Background="Beige" />
        <Button x:Name="BrowseAwardImage" Content="Browse" />
    </StackPanel>
    <TabControl>
        <TabItem Header="Award Categories">
            <StackPanel>
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="*" />
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto" />
                        <ColumnDefinition Width="*" />
                        <ColumnDefinition Width="Auto" />
                        <ColumnDefinition Width="*" />
                        <ColumnDefinition Width="Auto" />
                        <ColumnDefinition Width="Auto" />
                        <ColumnDefinition Width="Auto" />
                    </Grid.ColumnDefinitions>
                    <Label Content="Name" Grid.Column="0" Grid.Row="0" />
                    <TextBox x:Name="Description" Background="Beige" Grid.Column="1" Grid.Row="0" />

                    <Label Content="Reveal Time" Grid.Column="2" Grid.Row="0" />

                    <extToolkit:TimePicker Background="Beige" 
                                           Value="{Binding Path=RevealTime}" 
                                           Format="ShortTime" 
                                           ShowButtonSpinner="False" 
                                           Grid.Column="3" Grid.Row="0" 
                                           AllowSpin="False" />

                    <ComboBox x:Name="CategoryTypes" 
                              Background="Beige" 
                              Height="23" Width="120"
                              Grid.Column="4" Grid.Row="0" />

                    <Button Content="Add" Grid.Column="6" Grid.Row="0" 
                            cal:Message.Attach="[Event Click] = [Action Add($dataContext)]" />
                </Grid>
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="auto" />
                        <RowDefinition Height="*" />
                    </Grid.RowDefinitions>
                    <ScrollViewer Grid.Row="1" Margin="0,10,0,10">
                        <DataGrid  x:Name="Categories" CanUserAddRows="False" AutoGenerateColumns="False">
                            <DataGrid.Columns>
                                <DataGridTemplateColumn Header="Category Name" MinWidth="500">
                                    <DataGridTemplateColumn.CellTemplate>
                                        <DataTemplate>
                                            <StackPanel Orientation="Horizontal">
                                                <TextBlock Text="{Binding  Path=Description}" />
                                                <TextBlock Text="(" Margin="10,0,0,0" />
                                                <TextBlock Text="{Binding Path=Descriptor, Converter={StaticResource CategoryTypeConverter}, Mode=TwoWay}" />
                                                <TextBlock Text=")" Margin="0,0,10,0" />
                                            </StackPanel>
                                        </DataTemplate>
                                    </DataGridTemplateColumn.CellTemplate>
                                </DataGridTemplateColumn>
                                <DataGridTextColumn Header="Reveal Time" Binding="{Binding Path=RevealTime}" />
                                <DataGridTemplateColumn Header="Nominees">
                                    <DataGridTemplateColumn.CellTemplate>
                                        <DataTemplate>
                                            <Button Content="Edit" 
                                                    cal:Message.Attach="[Event Click] = [Action AddNominees(CategoryViewUserControl)]" />
                                        </DataTemplate>
                                    </DataGridTemplateColumn.CellTemplate>
                                </DataGridTemplateColumn>
                            </DataGrid.Columns>
                        </DataGrid>
                    </ScrollViewer>
                </Grid>
            </StackPanel>
        </TabItem>
        <TabItem Header="Award Images">
            <StackPanel>
                <Views:ImageView cal:Bind.Model="{Binding Path=Central.BusinessObjects.Wpf.ViewModels.ImageViewModel}" />
            </StackPanel>
        </TabItem>
    </TabControl>
</StackPanel>

ImageView.xaml

<UserControl x:Class="Central.BusinessObjects.Wpf.Views.ImageView"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto" />
        <ColumnDefinition />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition />
    </Grid.RowDefinitions>
    <Label x:Name="LabelName" Width="Auto" Grid.Column="0" Grid.Row="0"/>
    <Button x:Name="AddImages" Content="Add" Width="40" Grid.Column="1" Grid.Row="0"/>
    <ListView x:Name="SelectedImages" Grid.Column="0" Grid.Row="1" Grid.ColumnSpan="2">
        <ListView.View>
            <GridView>
                <GridViewColumn Width="Auto">
                    <TextBlock Text="{Binding Path=ImageUri}" />
                </GridViewColumn>
                <GridViewColumn>
                    <TextBlock Text="{Binding Path=Caption}" />
                </GridViewColumn>
            </GridView>
        </ListView.View>
    </ListView>
</Grid>    

The two view models are completely independent at the moment.

Upvotes: 0

Views: 4310

Answers (1)

devdigital
devdigital

Reputation: 34349

I can't say for sure without seeing more code, but I think the issue is that your TabControl's ItemsSource is bound to a collection of a Category type, so in your binding expression, Caliburn.Micro will attempt to bind each property on your Category type to a control on the ImageView.

Are you trying to have one category per tab? Where each tab displays something slightly differently? Either way, you probably should be binding your tab control to a collection of view models, rather than a collection of a Category type. Altenatively, perhaps a DataTemplateSelector to display the appropriate view based on the Category type.

Update

You would be better off having the ImageViewModel as a property of your CategoryViewModel. Instantiate the ImageViewModel in the CategoryViewModel (assigning it to the property), and then change your binding expression from:

<Views:ImageView cal:Bind.Model="{Binding Path=Central.BusinessObjects.Wpf.ViewModels.ImageViewModel}" />

to:

<Views:ImageView cal:Bind.Model="{Binding MyImageViewModelProperty}" />

The following may also work:

<ContentControl x:Name="MyImageViewModelProperty" />

Upvotes: 2

Related Questions