[2 days left] What’s wrong with your cloud strategy? Learn why multicloud solutions matter with Nimble Storage.Register Now

x
?
Solved

How to Get ObservableCollections field or column names using for each C# or VB in WPF

Posted on 2016-08-19
6
Medium Priority
?
472 Views
Last Modified: 2016-09-12
Hi guys,

I am trying to obtain the field names of a dynamic observable collection in a for each loop. The data is created at runtime so a bit trickier to get the property/fieldnames of the collection. I can bind to the field names in my XAML no problem and all works well but I need to get the names of all the fields that have been generated at runtime if possible, because I want to map these fields in an insert statement later in my code.

So I am assuming if I can bind items like below the field name does exist somewhere in the dynamic ObservableCollection:

        <!--<ListBox Grid.Column="1" Grid.Row="1"  Width="400" ItemsSource="{Binding SelectedItems}" Margin="5">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="{Binding FirstName}"/>
                        <TextBlock Text="{Binding LastName}"/>
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>-->

Open in new window



The current code I have is below which tries to loop through observable collection of which nothing happens:

        
    Private m_selectedItems As ObservableCollection(Of Object)
    Public ReadOnly Property SelectedItems() As ObservableCollection(Of Object)
        Get
            If m_selectedItems Is Nothing Then
                m_selectedItems = New ObservableCollection(Of Object)()
                m_selectedItems.Add(MyTestCollection)
            End If
            Return m_selectedItems
        End Get
    End Property

    Public Sub GetColumnsCollection()

        Dim myType As Type = SelectedItems.[GetType]()

        Dim props As IList(Of FieldInfo) = New List(Of FieldInfo)(myType.GetFields())

        For Each prop As FieldInfo In props
            Console.WriteLine(prop.FieldType.Name)
        Next

    End Sub

Open in new window


Thank you for your help in advance
0
Comment
Question by:databarracks
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 3
6 Comments
 
LVL 34

Expert Comment

by:it_saige
ID: 41763135
Use an ExpandoObject; e.g. -
Imports System.Collections.ObjectModel
Imports System.Dynamic
Imports System.Reflection

Module Module1
	ReadOnly people = (From i In Enumerable.Range(0, 20) Select New With {.ID = i, .FirstName = String.Format("FirstName{0}", i), .MiddleName = String.Format("MiddleName{0}", i), .LastName = String.Format("LastName{0}", i), .Birthdate = DateTime.Now.AddYears(-(9 * i)), .FullName = String.Format("{0} {1}. {2}", .FirstName, .MiddleName.First(), .LastName), .Age = String.Format("{0} years old", .Birthdate.Year - DateTime.Now.Year)}).ToList()

	Private m_selectedItems As ObservableCollection(Of ExpandoObject)
	Public ReadOnly Property SelectedItems() As ObservableCollection(Of ExpandoObject)
		Get
			If m_selectedItems Is Nothing Then
				m_selectedItems = New ObservableCollection(Of ExpandoObject)
				For Each p In people
					Dim obj = New ExpandoObject()
					For Each [property] As PropertyInfo In p.GetType().GetProperties()
						CType(obj, IDictionary(Of String, Object)).Add([property].Name, [property].GetValue(p, Nothing))
					Next
					m_selectedItems.Add(obj)
				Next
			End If
			Return m_selectedItems
		End Get
	End Property

	Sub Main()
		GetColumnsCollection()
		Console.ReadLine()
	End Sub

	Sub GetColumnsCollection()
		If SelectedItems IsNot Nothing AndAlso SelectedItems.Count > 0 Then
			For Each pair In SelectedItems(0)
				Console.WriteLine("Column: {0}; TypeOf: {1}", pair.Key, pair.Value.GetType())
			Next
		End If
	End Sub
End Module

Open in new window


Produces the following output -Capture.JPG
-saige-
0
 
LVL 34

Expert Comment

by:it_saige
ID: 41763149
Or for C# use dynamic's:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;

namespace EE_Q28964322
{
	class Program
	{
		static readonly dynamic people = (from i in Enumerable.Range(0, 20) 
								    let fName = string.Format("FirstName{0}", i)
								    let mName = string.Format("MiddleName{0}", i)
								    let lName = string.Format("LastName{0}", i)
								    let bDate = DateTime.Now.AddYears(-(9 * i))
								    select new
								    { 
									    ID = i, 
									    FirstName = fName, 
									    MiddleName = mName, 
									    LastName = lName, 
									    Birthdate = bDate, 
									    FullName = string.Format("{0} {1}. {2}", fName, mName.First(), lName), 
									    Age = string.Format("{0} years old", bDate.Year - DateTime.Now.Year)
								    });

		static ObservableCollection<dynamic> m_selectedItems;
		static ObservableCollection<dynamic> SelectedItems
		{
			get
			{
				if (m_selectedItems == null)
				{
					m_selectedItems = new ObservableCollection<dynamic>();
					foreach (var p in people)
						m_selectedItems.Add(p);
				}
				return m_selectedItems;
			}
		}

		static void Main(string[] args)
		{
			GetColumnsCollection();
			Console.ReadLine();
		}

		static void GetColumnsCollection()
		{
			if (SelectedItems != null && SelectedItems.Count > 0)
			{
				foreach (var property in SelectedItems[0].GetType().GetProperties())
					Console.WriteLine("Column: {0}; TypeOf: {1}", property.Name, property.GetValue(SelectedItems[0], null).GetType());
			}
		}
	}
}

Open in new window

Alternative GetColumnsCollections:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;

namespace EE_Q28964322
{
	class Program
	{
		static readonly dynamic people = (from i in Enumerable.Range(0, 20) 
								    let fName = string.Format("FirstName{0}", i)
								    let mName = string.Format("MiddleName{0}", i)
								    let lName = string.Format("LastName{0}", i)
								    let bDate = DateTime.Now.AddYears(-(9 * i))
								    select new
								    { 
									    ID = i, 
									    FirstName = fName, 
									    MiddleName = mName, 
									    LastName = lName, 
									    Birthdate = bDate, 
									    FullName = string.Format("{0} {1}. {2}", fName, mName.First(), lName), 
									    Age = string.Format("{0} years old", bDate.Year - DateTime.Now.Year)
								    });

		static ObservableCollection<dynamic> m_selectedItems;
		static ObservableCollection<dynamic> SelectedItems
		{
			get
			{
				if (m_selectedItems == null)
				{
					m_selectedItems = new ObservableCollection<dynamic>();
					foreach (var p in people)
						m_selectedItems.Add(p);
				}
				return m_selectedItems;
			}
		}

		static void Main(string[] args)
		{
			GetColumnsCollection();
			Console.ReadLine();
		}

		static void GetColumnsCollection()
		{
			if (SelectedItems != null && SelectedItems.Count > 0)
			{
				foreach (var property in SelectedItems.GetType().GetGenericArguments()[0].GetProperties())
					Console.WriteLine("Column: {0}; TypeOf: {1}", property.Name, property.GetValue(SelectedItems[0], null).GetType());
			}
		}
	}
}

Open in new window


Each produces the same output as above.

-saige-
0
 

Author Comment

by:databarracks
ID: 41764955
Thanks for the response. I still have an issue with all of your suggestions because of the for each inside selecteditems. The data can come from different sources so I cannot determine the class or object name as a user can chance the datasource at runtime based on their selection.
0
NFR key for Veeam Agent for Linux

Veeam is happy to provide a free NFR license for one year.  It allows for the non‑production use and valid for five workstations and two servers. Veeam Agent for Linux is a simple backup tool for your Linux installations, both on‑premises and in the public cloud.

 
LVL 34

Accepted Solution

by:
it_saige earned 2000 total points
ID: 41765672
The foreach is not type specific, it is dynamic which means that the compiler attempts to *infer* the structure of the passed object.  In vb.net the usage of an ExapandoObject over a DynamicObject was so that we could retain the properties from the original source object which, in all presented examples, is anonymous.

Consider the following, which gives us the same output -
Imports System.Collections.ObjectModel
Imports System.Dynamic
Imports System.Reflection

Module Module1
	ReadOnly people = (From i In Enumerable.Range(0, 20) Select New With {.ID = i, .FirstName = String.Format("FirstName{0}", i), .MiddleName = String.Format("MiddleName{0}", i), .LastName = String.Format("LastName{0}", i), .Birthdate = DateTime.Now.AddYears(-(9 * i)), .FullName = String.Format("{0} {1}. {2}", .FirstName, .MiddleName.First(), .LastName), .Age = String.Format("{0} years old", .Birthdate.Year - DateTime.Now.Year)}).ToList()

	Sub Main()
		Dim [collection] As New DynamicCollection(people)
		[collection].GetColumnsCollection()
		Console.ReadLine()
	End Sub
End Module

Class DynamicCollection
	Private ReadOnly m_selectedItems As ObservableCollection(Of ExpandoObject)
	Public ReadOnly Property SelectedItems()
		Get
			Return m_selectedItems
		End Get
	End Property

	Public Sub New(source As IEnumerable)
		If source IsNot Nothing Then
			m_selectedItems = New ObservableCollection(Of ExpandoObject)
			For Each item In source
				Dim obj = New ExpandoObject()
				For Each [property] As PropertyInfo In item.GetType().GetProperties()
					CType(obj, IDictionary(Of String, Object)).Add([property].Name, [property].GetValue(item, Nothing))
				Next
				m_selectedItems.Add(obj)
			Next
		End If
	End Sub

	Public Sub GetColumnsCollection()
		If SelectedItems IsNot Nothing AndAlso SelectedItems.Count > 0 Then
			For Each pair In SelectedItems(0)
				Console.WriteLine("Column: {0}; TypeOf: {1}", pair.Key, pair.Value.GetType())
			Next
		End If
	End Sub
End Class

Open in new window

-saige-
0
 

Author Comment

by:databarracks
ID: 41766474
Ahh I see:) That makes sense and my solution is now working as expected. Thank you so much for helping me out on this.........awesome work!!
0
 

Author Closing Comment

by:databarracks
ID: 41766475
it_saige was absolutely on the ball and would like to thank them for their help. First class help and detailed explanations
0

Featured Post

What is SQL Server and how does it work?

The purpose of this paper is to provide you background on SQL Server. It’s your self-study guide for learning fundamentals. It includes both the history of SQL and its technical basics. Concepts and definitions will form the solid foundation of your future DBA expertise.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Creating an analog clock UserControl seems fairly straight forward.  It is, after all, essentially just a circle with several lines in it!  Two common approaches for rendering an analog clock typically involve either manually calculating points with…
This article is for Object-Oriented Programming (OOP) beginners. An Interface contains declarations of events, indexers, methods and/or properties. Any class which implements the Interface should provide the concrete implementation for each Inter…
Have you created a query with information for a calendar? ... and then, abra-cadabra, the calendar is done?! I am going to show you how to make that happen. Visualize your data!  ... really see it To use the code to create a calendar from a q…
Are you ready to place your question in front of subject-matter experts for more timely responses? With the release of Priority Question, Premium Members, Team Accounts and Qualified Experts can now identify the emergent level of their issue, signal…

656 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question