Link to home
Start Free TrialLog in
Avatar of Alyanto
AlyantoFlag for United Kingdom of Great Britain and Northern Ireland

asked on

Access properties in nested observable collections

I have a View Model where there are nested Observable Collections.

ViewModelBase
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;

namespace SharedCode
{
    public class ViewModelBase : INotifyPropertyChanged, IDisposable
    {
        //public event PropertyChangedEventHandler PropertyChanged;
        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(string PropertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;

            if (handler != null) handler(this, new PropertyChangedEventArgs(PropertyName));
        }

        protected bool SetProperty<T>(ref T field, T value, string PropertyName)
        {
            if (EqualityComparer<T>.Default.Equals(field, value))
            {
                return false;
            }
            field = value;
            OnPropertyChanged(PropertyName);
            return true;
        }

        // Flag: Has Dispose already been called?
        bool disposed = false;

        // Instantiate a SafeHandle instance.
        SafeHandle handle = new SafeFileHandle(IntPtr.Zero, true);

        // Public implementation of Dispose pattern callable by consumers.
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        // Protected implementation of Dispose pattern.
        protected virtual void Dispose(bool disposing)
        {
            if (disposed)
                return;

            if (disposing)
            {
                handle.Dispose();
                // Free any other managed objects here.
                //
            }

            // Free any unmanaged objects here.
            //
            disposed = true;
        }
    }
}

Open in new window


The Contributor Mode which is nested in the deal model
using System;
using System.Linq;
using SharedCode;

namespace SAFEPanel.LatestDeal
{
    public class ModelDealContributors:ViewModelBase
    {
        public ModelDealContributors(string contributorname, string imagepath, double contributorpercentage)
        {
            ContributorName = contributorname;
            ContributorPercentage = contributorpercentage;
            Uri path = new Uri(imagepath);
            ImagePath = path;
        }

        string contributorName = "";
        public string ContributorName 
        {
            get { return contributorName; }
            set { SetProperty(ref contributorName, value, "ContributorName"); }
        }


        Uri imagePath = new Uri("C:\\Sabershare\\images\\NoConsultantImage.jpg");
        public Uri ImagePath 
        {
            get { return ImagePath; }
            set { SetProperty(ref imagePath, value, "ImagePath"); } 
        }

        double contributorPercentage = 0.0;
        public double ContributorPercentage 
        {
            get { return contributorPercentage; }
            set { SetProperty(ref contributorPercentage, value, "ContributorPercentage"); } 
        }
    }
}

Open in new window


The top level Deal model
using System;
using System.Collections.ObjectModel;
using System.Linq;


namespace SAFEPanel.LatestDeal
{
    public class ModelDealDetails:ViewModelBase
    {
        public ModelDealDetails()
        {
            LoadDeals();
        }

        private ModelDealDetails(string companyname, string candidatename, DateTime startdate, double fees )
        {
            CompanyName = companyname;
            CandidateName = candidatename;
            Startdate = startdate;
            Fees = fees;
        }

        public ObservableCollection<ModelDealContributors> Contributors = new ObservableCollection<ModelDealContributors>();
        public ObservableCollection<ModelDealDetails> DealDetails = new ObservableCollection<ModelDealDetails>();

        string companyName = string.Empty;
        public string CompanyName
        {
            get { return companyName; }
            set { SetProperty(ref companyName, value, "CompanyName"); }
        }

        string candidateName = string.Empty;
        public string CandidateName
        {
            get { return candidateName; }
            set { SetProperty(ref candidateName, value, "CandidateName"); }
        }

        DateTime startDate = DateTime.Now;
        public DateTime Startdate
        {
            get { return startDate; }
            set { SetProperty(ref startDate, value, "Startdate"); }
        }
        double fEes = 0.0;
        public double Fees
        {
            get { return fEes; }
            set { SetProperty(ref fEes, value, "Fees"); }
        }
        void LoadDeals()
        {
            ModelDealDetails Deal1 = new ModelDealDetails("Safe Computing", "Joe Smith", DateTime.Now, 500.00);
            Deal1.Contributors.Add(new ModelDealContributors("Tiny Deol", "C:\\Sabershare\\images\\Amrutha Nukala.jpg", 15));
            Deal1.Contributors.Add(new ModelDealContributors("Robert Patchy", "C:\\Sabershare\\images\\Charles Blockley.jpg", 25));
            Deal1.Contributors.Add(new ModelDealContributors("Paolo Kuba", "C:\\Sabershare\\images\\Chris Quinlan.jpg", 20));
            Deal1.Contributors.Add(new ModelDealContributors("james Smith", "C:\\Sabershare\\images\\George Gibbs.jpg", 40));
            DealDetails.Add(Deal1);

            ModelDealDetails Deal2 = new ModelDealDetails("Claires Accessories", "Shaun Tully", DateTime.Now, 850.00);
            Deal2.Contributors.Add(new ModelDealContributors("Tiny Deol", "C:\\Sabershare\\images\\Amrutha Nukala.jpg", 100));
            DealDetails.Add(Deal2);
            
        }
        void GetDealData()
        { }
    }
}

Open in new window


The View Model
using System;
using System.Collections.ObjectModel;
using System.Linq;
using SAFEPanel.SharedCode;

namespace SAFEPanel.LatestDeal
{
    public class ViewModelLatestDeal:ViewModelControl
    {

        public ViewModelLatestDeal()
        {
            ModelDealDetails modeldeals = new ModelDealDetails();
             Deals = modeldeals.DealDetails;
 
        }

        ObservableCollection<ModelDealDetails> deals = new ObservableCollection<ModelDealDetails>();
        public ObservableCollection<ModelDealDetails> Deals
        {
            get { return deals; }
            set { SetProperty(ref deals, value, "Deals"); }
        }
    }
}

Open in new window


The Control XAML please assume that DataContext ultimately = Deals and the collection at that level works fine.

<UserControl x:Class="SAFEPanel.LatestDeal.LatestDeal"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:xpanels="clr-namespace:SAFEPanel.XPanel"
             mc:Ignorable="d" Width="575" Height="239">
    <StackPanel>
        <ItemsControl ItemsSource="{Binding Deals}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Vertical" Background="AntiqueWhite">
                        <Border BorderBrush="Black" BorderThickness="2" CornerRadius="3" Margin="0,3,0,0">
                            <WrapPanel FlowDirection="RightToLeft" Background="Red">

                                <Grid HorizontalAlignment="Stretch" 
                                      VerticalAlignment="Stretch"
                                      Background="AntiqueWhite">
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width=".4*"/>
                                        <ColumnDefinition Width=".2*"/>
                                        <ColumnDefinition Width=".4*"/>
                                    </Grid.ColumnDefinitions>

                                    <StackPanel  Grid.Column="0" Background="Aqua" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
                                        <Label x:Name="CompanyName" 
                                               HorizontalAlignment="Left"
                                               HorizontalContentAlignment="Left"
                                               Content="{Binding CompanyName}" 
                                               Width="130" 
                                               Height="32"/>
                                        <Label x:Name="CandidateName" 
                                               HorizontalAlignment="Right"
                                               Content="{Binding CandidateName}" 
                                               Width="130" 
                                               Height="32"/>
                                        <Label x:Name="Startdate" 
                                               HorizontalAlignment="Left"
                                               Content="{Binding Startdate}" 
                                               Width="130" 
                                               Height="32"/>
                                        <Label x:Name="Fees" 
                                               HorizontalAlignment="Left"
                                               Content="{Binding Fees}" 
                                               Width="130" 
                                               Height="32"/>
                                    </StackPanel>
                                    <StackPanel Grid.Column="1" 
                                                Background="Green" 
                                                HorizontalAlignment="Stretch" 
                                                VerticalAlignment="Stretch">
                                        <Label x:Name="TitleCompanyName" 
                                               HorizontalAlignment="Left"
                                               HorizontalContentAlignment="Left"
                                               Content="Company" 
                                               Width="130" 
                                               Height="32"/>
                                        <Label x:Name="TitleCandidateName" 
                                               HorizontalAlignment="Left"
                                               Content="Candidate" 
                                               Width="130" 
                                               Height="32"/>
                                        <Label x:Name="TitleStartdate" 
                                               HorizontalAlignment="Left"
                                               Content="Start" 
                                               Width="130" 
                                               Height="32"/>
                                        <Label x:Name="TitleFees" 
                                               HorizontalAlignment="Left"
                                               Content="Fees" 
                                               Width="130" 
                                               Height="32"/>
                                    </StackPanel>

                                    <StackPanel Grid.Column="2" 
                                                Background="Purple" 
                                                HorizontalAlignment="Stretch" 
                                                VerticalAlignment="Stretch">
                                                   <Label x:Name="TitleCompanyName213" 
                                                   HorizontalAlignment="Left"
                                                   HorizontalContentAlignment="Left"
                                               
                                                   Content="{Binding Deal.Contributors.ContributorName}" 
                                                   Width="130" 
                                                   Height="32"/>
                                            </StackPanel>
                                         
                                </Grid>

                            </WrapPanel>
                        </Border>
                    </StackPanel>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>

    </StackPanel>
</UserControl>

Open in new window


This is the mark-up where I am struggling to connect to the sub Observable Collection

                                    <StackPanel Grid.Column="2" 
                                                Background="Purple" 
                                                HorizontalAlignment="Stretch" 
                                                VerticalAlignment="Stretch">
                                                   <Label x:Name="TitleCompanyName213" 
                                                   HorizontalAlignment="Left"
                                                   HorizontalContentAlignment="Left"
                                               
                                                   Content="{Binding Deal.Contributors.ContributorName}"
                                                   Width="130" 
                                                   Height="32"/>
                                            </StackPanel>

Open in new window


I have tried
 Content="{Binding Deal.Contributors.ContributorName}"

AND 

Content="{Binding Path= Contributors.ContributorName}"

AND 

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of Chris Stanyon
Chris Stanyon
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Alyanto

ASKER

Chris will the two list remain synchronised, that is contributors will relate to the deals?
Yes, because you're binding to the Contributors property of the individual Deal object.
Avatar of Alyanto

ASKER

I will give it a try in the morning an tell you how I get on with it, many thank
s so far
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Alyanto

ASKER

My intent is to award 1% of the reward to me and 99% to you because a small inspiration is great but knowledge is better.
Avatar of Alyanto

ASKER

Thank you for a great deal of help
Pleased you got it working.

Hadn't even noticed that you had a field and not a property!