0

I have little problem with binding. I have stackpanel in my xaml which has some elements in children collection. Second i have textblock which shows count of elements in stackpanel. It is done by binding that way

<TextBlock Text="{Binding Children.Count, ElementName=CommentsContainer, Mode=OneWay,  StringFormat=({0})}" />

<StackPanel x:Name="CommentsContainer"></StackPanel>

It works fine for first-time but if is something added to stackpanel children collection dinamically textblock text is not updated. I mean that collection count does not implement inotifypropertychange, but how do something like this properly?

Aldos
  • 193
  • 2
  • 12
  • 1
    Can you show us the C# code? Are you using [ObservableCollection](http://stackoverflow.com/questions/4279185/what-is-the-use-of-observablecollection-in-net) as collection? – Bruno V Jan 28 '15 at 13:28
  • What do you mean? Did you read question properly? StackPanel.Children is UIElementCollection. I just in code some times call StackPanel.Children.Add(Element), thats all from my code. – Aldos Jan 28 '15 at 13:33
  • The `Children` property of a `Panel` is of type `UIElementCollection` and as you correctly state this does not implement `INotifyPropertyChanged`. Therefore any changes to the `Count` property are not propagated via to the binding. In short, you cannot do what you are trying to do via binding to the `Count` property. – Steven Rands Jan 28 '15 at 13:40
  • Use MVVM and use a ListView with a StackPanel as ItemsPanel, then bind an ObservableCollection in your ViewModel to the ItemsSource of the ListView and the TextBlock to the Count-Property. – Lukas Körfer Jan 28 '15 at 13:46

1 Answers1

4

You asked "how [to] do something like this properly". The WPF way of doing it would be to have a collection of items implemented as a property on your Window or ViewModel or whatever, then bind an ItemsControl to that collection.

For example, if you had a collection of strings:

public ObservableCollection<string> MyItems { get; private set; }

// elsewhere in the same class...
MyItems = new ObservableCollection<string>();
MyItems.Add("first");
MyItems.Add("second");
MyItems.Add("etc");

ObservableCollection<T> is a good collection class to use for WPF as notification of any changes made to the collection (such as adding or removing items) will be pushed to any observers of the collection (such as WPF's binding system).

To see these items in your View (eg. Window, UserControl, etc), you would use a control that can display a list of items (one derived from ItemsControl) and bind that control to the list property, like so:

<Window ... >
    <StackPanel>
        <ItemsControl ItemsSource="{Binding MyItems}" />
        <TextBlock Text="{Binding MyItems.Count}" />
    </StackPanel>
</Window>

ObservableCollection<T> does implement INotifyPropertyChanged so the Count property will always reflect the actual number of items in the list.

You don't have to have a list of strings of course, they could be any kind of object. Similarly, you don't have to use an ItemsControl but could use something like a ListBox or ListView instead (they both derive from that base control class). Furthermore, you might want to look into data templating as this can be used to change the visual appearance of the items in the ItemsControl.

Steven Rands
  • 5,160
  • 3
  • 27
  • 56
  • Ok that's fine. Thanks, solution for my problem. But, is there a way how to set something like this to Grid instead of ItemsControl? – Aldos Jan 28 '15 at 16:33
  • An `ItemsControl` and a `Panel` are intended for different purposes. An items control uses a panel for layout, so in that sense you could have an items control using a `Grid` as its layout panel. However you cannot just replace an items control with a grid. – Steven Rands Jan 28 '15 at 16:43
  • Steven Rands did a great job explaining observable collections and especially so with templating; so much less code this way. @Aldos, if you would like to globally share a resource you can set x:Shared="false". Otherwise you can specify the resources for the grid with a template. I have put together some code to demonstrate: – Anthony Mason Feb 04 '15 at 16:18