Click here to Skip to main content
15,893,588 members
Articles / Desktop Programming / WPF

Reflection Studio - Part 1 - Introduction: Architecture and Design

Rate me:
Please Sign up or sign in to vote.
4.83/5 (23 votes)
22 Sep 2010GPL36 min read 60.1K   6.9K   111  
Reflection Studio is a "developer" application for assembly, database, performance, and code generation, written in C# under WPF 4.0.
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Controls;
using ReflectionStudio.Controls.Property;
using System.ComponentModel;
using System.Collections.Generic;
using System;

namespace ReflectionStudio.Controls
{
	public class PropertyGrid : Control
	{
		// Fields
		public static readonly DependencyProperty InstanceProperty =
			DependencyProperty.Register("Instance", typeof(object), typeof(PropertyGrid),
				new FrameworkPropertyMetadata(null, new PropertyChangedCallback(PropertyGrid.OnInstanceChanged),
													new CoerceValueCallback(PropertyGrid.CoerceInstance)));
		public static readonly DependencyProperty NullInstanceProperty =
			DependencyProperty.Register("NullInstance", typeof(object), typeof(PropertyGrid),
				new FrameworkPropertyMetadata(null, new PropertyChangedCallback(PropertyGrid.OnNullInstanceChanged)));

		public static readonly DependencyProperty PropertiesProperty =
			DependencyProperty.Register("Properties", typeof(ObservableCollection<PropertyBase>), typeof(PropertyGrid),
				new FrameworkPropertyMetadata(new ObservableCollection<PropertyBase>(),
												new PropertyChangedCallback(PropertyGrid.OnPropertiesChanged)));

		// Methods
		static PropertyGrid()
		{
			FrameworkElement.DefaultStyleKeyProperty.OverrideMetadata(typeof(PropertyGrid), new FrameworkPropertyMetadata(typeof(PropertyGrid)));
		}

		private static object CoerceInstance(DependencyObject d, object value)
		{
			PropertyGrid propertyGrid = d as PropertyGrid;
			if (value == null)
			{
				return propertyGrid.NullInstance;
			}
			return value;
		}

		private static void OnInstanceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
		{
			PropertyGrid propertyGrid = d as PropertyGrid;
			if (e.NewValue == null)
			{
				propertyGrid.Properties = new ObservableCollection<PropertyBase>();
			}
			else
			{
				propertyGrid.Properties = propertyGrid.Parse(e.NewValue);
			}
		}

		private static void OnNullInstanceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
		{
		}

		private static void OnPropertiesChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
		{
			PropertyGrid propertyGrid = d as PropertyGrid;

			ObservableCollection<PropertyBase> properties = e.OldValue as ObservableCollection<PropertyBase>;
			foreach (PropertyBase item in properties)
			{
				item.Dispose();
			}
		}

		// Properties
		public object Instance
		{
			get
			{
				return base.GetValue(InstanceProperty);
			}
			set
			{
				base.SetValue(InstanceProperty, value);
			}
		}

		public object NullInstance
		{
			get
			{
				return base.GetValue(NullInstanceProperty);
			}
			set
			{
				base.SetValue(NullInstanceProperty, value);
			}
		}

		public ObservableCollection<PropertyBase> Properties
		{
			get
			{
				return (ObservableCollection<PropertyBase>)base.GetValue(PropertiesProperty);
			}
			set
			{
				base.SetValue(PropertiesProperty, value);
			}
		}


		private ObservableCollection<PropertyBase> Parse(object instance)
		{
			ObservableCollection<PropertyBase> Items = new ObservableCollection<PropertyBase>();
			PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(instance);

			Dictionary<string, PropertyCategory> groups = new Dictionary<string, PropertyCategory>();
			List<PropertyItem> propertyCollection = new List<PropertyItem>();

			foreach (PropertyDescriptor propertyDescriptor in properties)
			{
				this.CollectProperties(instance, propertyDescriptor, propertyCollection);
			}

			foreach (PropertyItem property in propertyCollection)
			{
				PropertyCategory propertyCategory;
				if (groups.ContainsKey(property.Category))
				{
					propertyCategory = groups[property.Category];
				}
				else
				{
					propertyCategory = new PropertyCategory(property.Category);
					groups[property.Category] = propertyCategory;
					Items.Add(propertyCategory);
				}

				propertyCategory.Items.Add(property);
			}

			return Items;
		}

		private void CollectProperties(object instance, PropertyDescriptor descriptor, List<PropertyItem> propertyCollection)
		{
			if (descriptor.Attributes[typeof(FlatAttribute)] == null)
			{
				if (descriptor.IsBrowsable)
				{
					PropertyItem property = new PropertyItem(instance, descriptor);
					propertyCollection.Add(property);
				}
			}
			else
			{
				instance = descriptor.GetValue(instance);
				PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(instance);
				foreach (PropertyDescriptor propertyDescriptor in properties)
				{
					this.CollectProperties(instance, propertyDescriptor, propertyCollection);
				}
			}
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)


Written By
Architect
France France
WPF and MVVM fan, I practice C # in all its forms from the beginning of the NET Framework without mentioning C ++ / MFC and other software packages such as databases, ASP, WCF, Web & Windows services, Application, and now Core and UWP.
In my wasted hours, I am guilty of having fathered C.B.R. and its cousins C.B.R. for WinRT and UWP on the Windows store.
But apart from that, I am a great handyman ... the house, a rocket stove to heat the jacuzzi and the last one: a wood oven for pizza, bread, and everything that goes inside

https://guillaumewaser.wordpress.com/
https://fouretcompagnie.wordpress.com/

Comments and Discussions