Search code examples
wpfdata-bindingienumerable

Unable to Bind ListBox to IEnumerable<object>


This is the first time I'm working with List

Here is my code (Removed all the unwanted lines for simplification)

Class1

public class RInfo 
{
    public int RCode { get; set; }
    public int ACode { get; set; }
    public int DCode { get; set; }
    public string RNo { get; set; }
    //public DateTime EDate { get; set; }
    //public DateTime? VDate { get; set; }
}

Class 2

public class DInfo 
{
    public int DCode { get; set; }
    public string DName { get; set; }
    public bool DCExpires { get; set; }
}

Class that I will get after joining above two classes

public class RInfo_Details
{
    public int RCode { get; set; }
    public int ACode { get; set; }
    public int DCode { get; set; }
    public string DCName { get; set; }
    public string DName { get; set; }
    public string RNo { get; set; }
    //public DateTime EDate { get; set; }
    //public DateTime? VDate { get; set; }
}

Here is my class this is used to retrive data and for binding in XAML

public class AppData : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    protected void RaisePropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));

    private AppData() { }

    private static AppData instance = null;

    public static AppData Instance
    {
        get
        {
            if (instance == null) instance = new AppData();
            return instance;
        }
    }

    AInfo _SelAInfo;
    public AInfo SelAInfo
    {
        get => _SelAInfo; set
        {
            _SelAInfo = value; RaisePropertyChanged(nameof(SelAInfo));
            RaisePropertyChanged(nameof(RInfo_List));
            RaisePropertyChanged(nameof(RInfoDetailedList));
        }
    }

    List<DInfo> _DInfo;
    public List<DInfo> DInfo { get => _DInfo; set { _DInfo = value; RaisePropertyChanged(nameof(DInfo)); } }

    List<RInfo> _RInfo;
    public List<RInfo> RInfo { get => _RInfo; set { _RInfo = value; RaisePropertyChanged(nameof(RInfo)); RaisePropertyChanged(nameof(RInfoDetailedList)); } }

    public IEnumerable<RInfo_Details> RInfoDetailedList
    {
        get
        {
            IEnumerable<RInfo_Details> newlist = (from r in RInfo
                                                  join d in DInfo
                                                  on r.DCode equals d.DCode
                                                  select new
                                                  {
                                                      r.RCode,
                                                      r.ACode,
                                                      r.DCode,
                                                      d.DName,
                                                      d.DCExpires,
                                                      r.RNo,
                                                  }).ToList() as IEnumerable<RInfo_Details>;

            return newlist as IEnumerable<RInfo_Details>;
        }
    }

    public void iniTestData()
    {
        this.DInfo = new List<DInfo>()
        {
            new DInfo{DCode=1, DCExpires=false, DName="PAN" },
            new DInfo{DCode=2, DCExpires=true, DName="FSSAI" },
            new DInfo{DCode=3, DCExpires=false, DName="AANDAHR" }
        };

        this.RInfo = new List<RInfo>()
        {
            new RInfo{RCode=1, ACode=1, DCode=1, RNo="PAN NO ACode 1" },
            new RInfo{RCode=2, ACode=2, DCode=1, RNo="PAN NO ACode 2" },
            new RInfo{RCode=3, ACode=5, DCode=3, RNo="AADHAR ACode 5" },
            new RInfo{RCode=4, ACode=4, DCode=1, RNo="PAN NO ACode 4" }
        };
    }
}

Here is code in XAML that is binding AppData.RInfoDetailedList

        <ListView ItemsSource="{Binding Source={x:Static local:AppData.Instance}, Path=RInfoDetailedList}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition/>
                        <ColumnDefinition/>
                        <ColumnDefinition/>
                    </Grid.ColumnDefinitions>
                    <Label Grid.Column="0" Content="{Binding RNo}"/>
                    <Label Grid.Column="1" Content="{Binding DName}"/>
                    <Label Grid.Column="2" Content="{Binding DCExpires }"/>
                </Grid>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>

Data from RInfo & DInfo Binds succesfully. but from RInfoDetailedList does not bind. What is that I'm missing


Solution

  • This is because RInfoDetailedList is returning null due to the wrong cast!

    You can create the RInfo_Details object in the select statement like this

    public IEnumerable<RInfo_Details> RInfoDetailedList
    {
        get
        {
            if (RInfo == null || DInfo == null) return null;   
            var newList = from r in RInfo
                join d in DInfo
                    on r.DCode equals d.DCode
                select new RInfo_Details {
                    RCode = r.RCode,
                    ACode = r.ACode,
                    DCode = r.DCode,
                    DName = d.DName,
                    RNo = r.RNo,
                };
    
            return newList;
        }
    }