locked
Binding to properties on ObservableCollection problem RRS feed

  • Question

  • I want to bind to the Count property of an ObservableCollection but strangely the value always shown in the UI is zero.  I have been staring at this for too long and it must be something obvious...

                        <GridViewColumn Header="test" DisplayMemberBinding="{Binding Path=ViewModelList.Count}" />
    
    Sunday, December 13, 2009 11:18 PM

Answers

  • The DataContext of each row in your GridView is going to be an item in the ItemSource of the GridView... your binding may be looking for a property called Count on each item in the ObservableCollection rather than collection itself. 


    The binding you have will work if you want the Count property of each item, otherwise, you need to use a RelativeSource binding to get from the DataContext of the GridView row in question back to the ItemsSource of the GridView itself.

    XAML
     <ListView ItemsSource="{Binding AllItems}">
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}" ></GridViewColumn>
                    <GridViewColumn Header="IsSelected" DisplayMemberBinding="{Binding IsSelected}" ></GridViewColumn>
                    <GridViewColumn Header="AllItems.MyItems.Count" DisplayMemberBinding="{Binding MyItems.Count}" ></GridViewColumn>
                    <GridViewColumn Header="GridView.ItemsSource.Count" DisplayMemberBinding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListView}}, Path=ItemsSource.Count}" ></GridViewColumn>                
                </GridView>
            </ListView.View>
        </ListView>

    CODE
    public partial class Window1 : Window
    {
        public ObservableCollection<SillyClass> AllItems { get; set; }

        public Window1()
        {
            InitializeComponent();

            AllItems = new ObservableCollection<SillyClass>() 
            {
                new SillyClass() 
                { 
                    Name = "Matt",
                    MyItems = new List<string>() { "Item 1", "Item 2"}
                },
                new SillyClass() 
                { 
                    Name = "Jesper", 
                    IsSelected = true,
                    MyItems = new List<string>() { "Item 1", "Item 2", "Item 3"}
                },
            };
            
            this.DataContext = this;
        }
    }

    public class SillyClass 
    {
        public string Name {get; set;}
        public bool IsSelected {get; set;}
        public List<string> MyItems { get; set; }
    }

    Warm Regards,
    Matt
    • Proposed as answer by Zhi-Xin Ye Monday, December 14, 2009 8:07 AM
    • Marked as answer by Zhi-Xin Ye Wednesday, December 23, 2009 8:30 AM
    Monday, December 14, 2009 12:52 AM

All replies

  • The DataContext of each row in your GridView is going to be an item in the ItemSource of the GridView... your binding may be looking for a property called Count on each item in the ObservableCollection rather than collection itself. 


    The binding you have will work if you want the Count property of each item, otherwise, you need to use a RelativeSource binding to get from the DataContext of the GridView row in question back to the ItemsSource of the GridView itself.

    XAML
     <ListView ItemsSource="{Binding AllItems}">
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}" ></GridViewColumn>
                    <GridViewColumn Header="IsSelected" DisplayMemberBinding="{Binding IsSelected}" ></GridViewColumn>
                    <GridViewColumn Header="AllItems.MyItems.Count" DisplayMemberBinding="{Binding MyItems.Count}" ></GridViewColumn>
                    <GridViewColumn Header="GridView.ItemsSource.Count" DisplayMemberBinding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListView}}, Path=ItemsSource.Count}" ></GridViewColumn>                
                </GridView>
            </ListView.View>
        </ListView>

    CODE
    public partial class Window1 : Window
    {
        public ObservableCollection<SillyClass> AllItems { get; set; }

        public Window1()
        {
            InitializeComponent();

            AllItems = new ObservableCollection<SillyClass>() 
            {
                new SillyClass() 
                { 
                    Name = "Matt",
                    MyItems = new List<string>() { "Item 1", "Item 2"}
                },
                new SillyClass() 
                { 
                    Name = "Jesper", 
                    IsSelected = true,
                    MyItems = new List<string>() { "Item 1", "Item 2", "Item 3"}
                },
            };
            
            this.DataContext = this;
        }
    }

    public class SillyClass 
    {
        public string Name {get; set;}
        public bool IsSelected {get; set;}
        public List<string> MyItems { get; set; }
    }

    Warm Regards,
    Matt
    • Proposed as answer by Zhi-Xin Ye Monday, December 14, 2009 8:07 AM
    • Marked as answer by Zhi-Xin Ye Wednesday, December 23, 2009 8:30 AM
    Monday, December 14, 2009 12:52 AM
  • Yes, each item in the items source (another ObservableCollection) has a property called ViewModelList which is an ObservableCollection and I want to show the Count for that array for each item in the list view. 

    Regards,
    Tuesday, December 15, 2009 5:09 AM
  • Yep, so in the example I showed, the AllItems property is your ItemsSource, and your ViewModelList is the MyItems property.

    Perhaps make sure that ViewModelList is a public property with a getter.

    eg.

    public ObservableCollection<ViewModelBase> ViewModelList {get; set;}


    Regards,
    Matt
    Tuesday, December 15, 2009 5:39 AM
  • Hi Matt,

    Yes, it is public and used by many other objects.  The strange thing is that the call always returns 0.  I step into the debugger and the list is not zero length.  Maybe it is time I simplify the code so I can post an example to demonstrate the issue.  I'll work on that over the next day or two.
    Wednesday, December 16, 2009 4:35 AM
  • Perhaps check the Output window and see if the Binding is failing for some reason.
    Wednesday, December 16, 2009 4:45 AM
  • The binding does not fail as I do see a zero in the column as opposed to nothing.
    Wednesday, December 16, 2009 7:18 PM
  • True. Can you post the repro? The only other thing I can think of is that the UI is not being updated after the size of the collection has changed.
    Thursday, December 17, 2009 12:09 AM