Home > Enterprise >  Data Binding to a Property within a Collection in another Collection
Data Binding to a Property within a Collection in another Collection

Time:12-06

I'm having an issue databinding to a property that is two levels deep in a collection.

The object is structured as such Collection --Data --Name --Collection --Name --Data

So essentially its a collection within a collection, and I can't seem to bind to the name within the contained collection. I can bind to all the properties of the initial collection, including the collection within it, but as soon as I try to bind to the name property of the internal collection I get bad bindings.

XAML Portion

<TabControl ItemsSource="{Binding Path=BMOverlayCollection}" Grid.Column="0" Grid.Row="4" Grid.ColumnSpan="4">
            <TabControl.ItemTemplate>
                <!-- this is the header template-->
                <DataTemplate>
                    <TextBlock
                Text="{Binding Name}" />
                </DataTemplate>
            </TabControl.ItemTemplate>
            <TabControl.ContentTemplate>
                <!-- this is the body of the TabItem template-->
                <DataTemplate>
                    <TextBlock
                Text="{Binding Graphics.Name}" />
                </DataTemplate>
            </TabControl.ContentTemplate>
        </TabControl>

C# Portion

    public class BMGraphicsOverlayCollection : INotifyPropertyChanged, IEnumerable
    {
    #region Event Property
    public event PropertyChangedEventHandler? PropertyChanged;
        protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
        #endregion

        private ObservableCollection<NamedOverlay> _namedOverlays;
        public ObservableCollection<NamedOverlay> NamedOverlays { get { return _namedOverlays; } set { _namedOverlays = value; OnPropertyChanged(); } }

        public BMGraphicsOverlayCollection()
        {
            _namedOverlays = new ObservableCollection<NamedOverlay>(); 
        }
        public void Add(string name, GraphicsOverlay overlay)
        {
            NamedOverlay mOverlay = new NamedOverlay();
            mOverlay.Name = name;
            mOverlay.Overlay = overlay;
            _namedOverlays.Add(mOverlay);
        }

        public void Add(string name, GraphicsOverlay overlay, IList<MapGraphic> graphics)
        {
            NamedOverlay mOverlay = new NamedOverlay();
            mOverlay.Name = name;
            mOverlay.Overlay = overlay;
            mOverlay.Graphics = new ObservableCollection<MapGraphic>(graphics);
            _namedOverlays.Add(mOverlay);
        }

        public IEnumerator GetEnumerator()
        {
            return _namedOverlays.GetEnumerator();
        }
    }
    public class NamedOverlay : INotifyPropertyChanged
    {
        #region Event Property
        public event PropertyChangedEventHandler? PropertyChanged;
        protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
        #endregion
        private string _name;
        public string Name { get { return _name; } set { _name = value; OnPropertyChanged(); } }
        private GraphicsOverlay _overlay;
        public GraphicsOverlay Overlay { get { return _overlay; } set { _overlay = value; OnPropertyChanged(); } }
        private ObservableCollection<MapGraphic> _graphics;
        public ObservableCollection<MapGraphic> Graphics { get { return _graphics; } set { _graphics = value; OnPropertyChanged(); } }
    }

}

And the MapGraphic pertinent part

        private string _name;
    public string Name
    {
        get
        {
            if (_name == null)
            {
                return "Unnamed";
            } else
            {
                return _name;
            }
        }
        set
        {
            _name = value; OnPropertyChanged();
        }
    }

Thanks in advance for the help.

CodePudding user response:

According to your code, Your data structure was NamedOverlays[].Graphics[].Name, but your binding path was NamedOverlays[].Graphics.Name. That's the reason of the bad binding. Change

<TextBlock Text="{Binding Graphics.Name}" />

to (if you want to show all names in Graphics)

<ListBox ItemsSource="{Binding Graphics}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Name}"/>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

or (if you just want to show 1st name in graphics)

<TextBlock Text="{Binding Graphics[0].Name}" />

will fix the problem.

  • Related