property bound multiple times

Topics: Prism v2 - Silverlight 3
Nov 9, 2009 at 1:21 AM

Hi,

In my MVVM -Silverlight project, I have a collection of images that I want to display differently based on some conditions. To accomplish this, in my model class I have a ImagesList property of type List<Image>. I have bound this property to two ItemsControl control. At any given time, only one of the ItemsControl has its Visibility set to 'Visible', the other is 'Collapsed'.

When I do this, the image list shows up in only one of the ItemsControl, and not the other. But when I create another property say 'ImagesList_2' in my model class and assign this to the second ItemsControl, everything works fine.

Why is it that I'm not allowed to bind a property to multiple controls or am I doing something wrong?

Thanks
Arun

Nov 9, 2009 at 7:45 AM

Do you have any code that you can share with us, I can't really follow what you're trying to accomplish.

Cheers,
Ted

Nov 9, 2009 at 4:05 PM

Neo,

Here's my model class:

 

public class MetricsItem
{
    public List<RatingsByAlbum> AlbumRatings { get; set; }
}

public class RatingsByAlbum
{
    public Image LeftImage { get; set; }
    public Image RightImage { get; set; }
}

public class Image
{
    private const string SiteName = "http://localhost:1501";
    private string imagePath;
    private string isPreferred;

    public string ImagePath
    {
        get
        {
            return imagePath;
        }
        set
        {
            imagePath = string.Format("{0}/{1}", SiteName, value.Replace("\\", "/"));
        }
    }
    public string RateCount { get; set; }
    public string AverageScore { get; set; }
    public string IsPreferred { get; set; }

}

and here's the xaml that I'm trying to bind the list to:

 

 

<controls:Accordion x:Name="AccordionPane" Grid.Row="0" Grid.Column="0"
                    DataContext="{Binding MetricsItems[0]}"
                    Width="780">
    <controls:AccordionItem Header="Ratings By Album" Width="770">
        <ContentControl>
            <StackPanel Orientation="Vertical" Height="360" Width="760" >
                <ScrollViewer x:Name="ImagesViewer" Height="320"
                              Visibility="{Binding Path=ImagesViewerVisibility}">
                    <ItemsControl ItemsSource="{Binding Path=AlbumRatings}">
                        <ItemsControl.ItemTemplate>
                            <DataTemplate>
                                <Grid Width="760">
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="370"/>
                                        <ColumnDefinition Width="20"/>
                                        <ColumnDefinition Width="370"/>
                                    </Grid.ColumnDefinitions>
                                    <Grid.RowDefinitions>
                                        <RowDefinition />
                                        <RowDefinition Height="10"  />
                                    </Grid.RowDefinitions>
                                    <Grid Grid.Column="0" Grid.Row="0" Width="360">
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition />
                                        </Grid.ColumnDefinitions>
                                        <Grid.RowDefinitions>
                                            <RowDefinition Height="240" />
                                            <RowDefinition Height="10"/>
                                            <RowDefinition Height="80"/>
                                        </Grid.RowDefinitions>
                                        <Image Grid.Column="0" Grid.Row="0"
                                               Source="{Binding Path=LeftImage.ImagePath}" 
                                               VerticalAlignment="Center" 
                                               HorizontalAlignment="Center" />
                                        <Grid Grid.Column="0" Grid.Row="2" Width="360" 
                                              VerticalAlignment="Center"
                                              HorizontalAlignment="Center" >
                                            <Grid.ColumnDefinitions>
                                                <ColumnDefinition />
                                                <ColumnDefinition Width="250"/>
                                            </Grid.ColumnDefinitions>
                                            <Grid.RowDefinitions>
                                                <RowDefinition />
                                                <RowDefinition />
                                                <RowDefinition />
                                                <RowDefinition />
                                                <RowDefinition />
                                            </Grid.RowDefinitions>
                                            <TextBlock Text="{Binding Path=LeftImage.RateCount}"
                                                       Grid.Column="1" Grid.Row="2" />
                                            <TextBlock Text="{Binding Path=LeftImage.AverageScore}"
                                                       Grid.Column="1" Grid.Row="3" />
                                            <TextBlock Text="{Binding Path=LeftImage.IsPreferred}"
                                                       Grid.Column="1" Grid.Row="4" />
                                        </Grid>
                                    </Grid>
                                    <Grid Grid.Column="2" Grid.Row="0">
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition />
                                        </Grid.ColumnDefinitions>
                                        <Grid.RowDefinitions>
                                            <RowDefinition Height="240" />
                                            <RowDefinition Height="10"/>
                                            <RowDefinition Height="80"/>
                                        </Grid.RowDefinitions>
                                        <Image Grid.Column="0" Grid.Row="0"
                                               Source="{Binding Path=RightImage.ImagePath}" 
                                               VerticalAlignment="Center" 
                                               HorizontalAlignment="Center" />
                                        <Grid Grid.Column="0" Grid.Row="2" Width="360"  
                                              VerticalAlignment="Center"
                                              HorizontalAlignment="Center">
                                            <Grid.ColumnDefinitions>
                                                <ColumnDefinition />
                                                <ColumnDefinition Width="250"/>
                                            </Grid.ColumnDefinitions>
                                            <Grid.RowDefinitions>
                                                <RowDefinition />
                                                <RowDefinition />
                                                <RowDefinition />
                                                <RowDefinition />
                                                <RowDefinition />
                                            </Grid.RowDefinitions>
                                            <TextBlock Text="{Binding Path=RightImage.RateCount}"
                                                       Grid.Column="1" Grid.Row="2" />
                                            <TextBlock Text="{Binding Path=RightImage.AverageScore}"
                                                       Grid.Column="1" Grid.Row="3" />
                                            <TextBlock Text="{Binding Path=RightImage.IsPreferred}"
                                                       Grid.Column="1" Grid.Row="4" />
                                        </Grid>
                                    </Grid>
                                </Grid>
                            </DataTemplate>
                        </ItemsControl.ItemTemplate>
                    </ItemsControl>
                </ScrollViewer>
                <ScrollViewer x:Name="PanoramasViewer" Height="320"
                              Visibility="{Binding Path=PanoramasViewerVisibility}">
                    <ItemsControl ItemsSource="{Binding Path=PanoramaAlbumRatings}">
                        <ItemsControl.ItemTemplate>
                            <DataTemplate>
                                <StackPanel Orientation="Vertical">
                                    <Grid Width="760">
                                        <Grid.RowDefinitions>
                                            <RowDefinition />
                                            <RowDefinition Height="20" />
                                            <RowDefinition Height="20" />
                                            <RowDefinition Height="20" />
                                            <RowDefinition Height="20" />
                                        </Grid.RowDefinitions>
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition Width="540"/>
                                            <ColumnDefinition Width="10"/>
                                            <ColumnDefinition Width="220"/>
                                        </Grid.ColumnDefinitions>
                                        <Image Source="{Binding Path=LeftImage.ImagePath}" 
                                               Width="760" Grid.Row="0" Grid.Column="0" 
                                               Grid.ColumnSpan="3" />
                                        <TextBlock Text="{Binding Path=LeftImage.RateCount}"
                                                   Grid.Column="2" Grid.Row="2" />
                                        <TextBlock Text="{Binding Path=LeftImage.AverageScore}"
                                                   Grid.Column="2" Grid.Row="3" />
                                        <TextBlock Text="{Binding Path=LeftImage.IsPreferred}"
                                                       Grid.Column="1" Grid.Row="4" />
                                    </Grid>
                                    <Grid Width="760">
                                        <Grid.RowDefinitions>
                                            <RowDefinition />
                                            <RowDefinition Height="20" />
                                            <RowDefinition Height="20" />
                                            <RowDefinition Height="20" />
                                            <RowDefinition Height="20" />
                                        </Grid.RowDefinitions>
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition Width="540"/>
                                            <ColumnDefinition Width="10"/>
                                            <ColumnDefinition Width="210"/>
                                        </Grid.ColumnDefinitions>
                                        <Image Source="{Binding Path=RightImage.ImagePath}" 
                                               Width="760" Grid.Row="0" Grid.Column="0" 
                                               Grid.ColumnSpan="3" />
                                        <TextBlock Text="{Binding Path=RightImage.RateCount}"
                                                   Grid.Column="2" Grid.Row="2" />
                                        <TextBlock Text="{Binding Path=RightImage.AverageScore}"
                                                   Grid.Column="2" Grid.Row="3" />
                                        <TextBlock Text="{Binding Path=RightImage.IsPreferred}"
                                                   Grid.Column="2" Grid.Row="4" />
                                    </Grid>
                                </StackPanel>
                            </DataTemplate>
                        </ItemsControl.ItemTemplate>
                    </ItemsControl>
                </ScrollViewer>
            </StackPanel>
        </ContentControl>
    </controls:AccordionItem>
</controls:Accordion>

 

Now I need to display either panorama images or regular images. To accomplish this, I populate the AlbumRatings property of type List<RatingsByAlbum> in the MetricsItem class, whether it is the panorama image or not. During data binding, I bind the AlbumRatings property to either the ItemsControl under the ImagesViewer scroller or one under PanoramasViewer scroller and I collapse the other scroll viewer.

The regular images show up perfectly fine under the ImagesViewer scroller, but for some reason, nothing shows up under the PanoramasViewer. Also, when I created a new property PanoramaAlbumRatings of the same type in my MetricsItem class and bound it to the ItemsControl in PanoramasViewer, they both work just fine. Why?

Arun

Nov 10, 2009 at 9:42 PM

Hi,

That's probably because your PanoramaViewer's ItemsControl has it's ItemsSource property set as: ItemsSource="{Binding Path=PanoramaAlbumRatings}", but you have no "PanoramaAlbumRatings" property on your MetricsItem. :) Try changing the binding to Path=AlbumRatings instead, or add another Property on your MetricsItem called PanoramaAlbumRatings which your populate with your panorama images.

Cheers,
Ted

Nov 10, 2009 at 10:18 PM

My apologies Neo, my intention was to reduce the clutter in my code to ease user reading here and during this process, I messed up slightly.

In my actual class, there IS a PanoramaAlbumRatings property and the app works fine when I set the second ItemsControl ItemSource to the PanoranaAlbumRatings property and the first one to AlbumRatings property. But when I set both of them to AlbumRatings, neither the images nor the text shows up for the second ItemsControl control.

I should have checked the xaml one more time before posting.. sorry again for the confusion, but this is still bugging me and I'm running out of search strings to get to someone's posting about this.

Arun

Nov 10, 2009 at 11:25 PM

Ahh, what a shame. I was hoping we had nailed it... :) Ok, so what else... are you sure you have filled your lists with data before introducing your model as a datacontext? (I'm asking since your MetricsItem doesn't implement INotifyPropertyChanged, and hence the binding system won't know if you're changing data, therefore if you databind first, and only after that start adding Albums the view won't know about it... just checking... I actually strong would suggest that you implement that for all your properties, and instead of relying on List<RatingsByAlbum> you should have ObservableCollection<RatringsByAlbum>, so that the bindingsystem knows when you're adding/deleting items.

Cheers,
Ted

Btw, we probably should move this whole thread to the wpf forums instead (http://social.msdn.microsoft.com/Forums/en/wpf/threads), not to clutter the prism forums.

Nov 10, 2009 at 11:49 PM

Ted,

That makes complete sense, except one thing: Why is it that the binding system recognizes the binding for the first ItemsControl? The data binding occurs first and only then I add items to the AlbumRatings collection.

Since I don't have the INotifyPropertyChanged implemented, I am thinking of working on a small-scale project to test this. If it doesn't work there, I'll give you the entire code and you can have a look at it.

I'll start working on the project and I (hopefully) won't have to upload the project for you and get the solution through INotifyPropertyChanged.

Thanks for your help,
Arun

Nov 11, 2009 at 6:13 AM

Ted,

I got it fixed. I implemented INotifyPropertyChanged on MetricsItem and it works now. Thanks a lot for your help.

Arun

 

Nov 11, 2009 at 8:30 PM

Changing the collection property from List<> to an ObservableCollection<> could've also done the trick, but having the model class implement INotifyPropertyChanged makes it look lot more structured.