Click here to Skip to main content
15,884,353 members
Articles / Programming Languages / C#

DSGraphEdit: A Reasonable Facsimile of Microsoft's GraphEdit in .NET

Rate me:
Please Sign up or sign in to vote.
4.93/5 (79 votes)
28 Jan 2018MIT7 min read 295.8K   10K   142  
A library for adding DirectShow GraphEdit-like abilities to .NET applications
namespace PropertyGridEx
{
    using Microsoft.VisualBasic;
    using System;
    using System.Collections;
    using System.ComponentModel;
    using System.Drawing.Design;
    using System.Runtime.CompilerServices;
    using System.Runtime.InteropServices;
    using System.Data;
    using System.Xml.Serialization;

    [Serializable(), XmlRootAttribute("CustomProperty")]
    public class CustomProperty
    {				
		#region "Private variables"
		
		// Common properties
		protected string sName = "";
		protected object oValue = null;
		protected bool bIsReadOnly = false;
		protected bool bVisible = true;
		protected string sDescription = "";
		protected string sCategory = "";
		protected bool bIsPassword = false;
		protected bool bIsPercentage = false;
		protected bool bParenthesize = false;
		
		// Filename editor properties
		protected string sFilter = null;
		protected UIFilenameEditor.FileDialogType eDialogType = UIFilenameEditor.FileDialogType.LoadFileDialog;
		protected bool bUseFileNameEditor = false;
		
		// Custom choices properties
		protected CustomChoices oChoices = null;
		
		// Browsable properties
		protected bool bIsBrowsable = false;
		protected BrowsableTypeConverter.LabelStyle eBrowsablePropertyLabel = BrowsableTypeConverter.LabelStyle.lsEllipsis;
		
		// Dynamic properties
		protected bool bRef = false;
		protected object oRef = null;
		protected string sProp = "";
		
		// Databinding properties
		protected object oDatasource = null;
		protected string sDisplayMember = null;
		protected string sValueMember = null;
		protected object oSelectedValue = null;
		protected object oSelectedItem = null;
		protected bool bIsDropdownResizable = false;
		
		// 3-dots button event handler
		protected UICustomEventEditor.OnClick MethodDelegate;
		
		// Extended Attributes
		[NonSerialized()]protected AttributeCollection oCustomAttributes = null;
		protected object oTag = null;
		protected object oDefaultValue = null;
		protected Type oDefaultType = null;
		
		// Custom Editor and Custom Type Converter
		[NonSerialized()]protected UITypeEditor oCustomEditor = null;
		[NonSerialized()]protected TypeConverter oCustomTypeConverter = null;
		
		#endregion
		
		#region "Public methods"
		
		public CustomProperty()
		{
			sName = "New Property";
			oValue = new string(' ',0);
		}
		
		public CustomProperty(string strName, object objValue, bool boolIsReadOnly, string strCategory, string strDescription, bool boolVisible)
		{
			sName = strName;
			oValue = objValue;
			bIsReadOnly = boolIsReadOnly;
			sDescription = strDescription;
			sCategory = strCategory;
			bVisible = boolVisible;
			if (oValue != null)
			{
				oDefaultValue = oValue;
			}
		}
		
		public CustomProperty(string strName, ref object objRef, string strProp, bool boolIsReadOnly, string strCategory, string strDescription, bool boolVisible)
		{
			sName = strName;
			bIsReadOnly = boolIsReadOnly;
			sDescription = strDescription;
			sCategory = strCategory;
			bVisible = boolVisible;
			bRef = true;
			oRef = objRef;
			sProp = strProp;
			if (Value != null)
			{
				oDefaultValue = Value;
			}
		}

        public void RebuildAttributes()
        {
            if (bUseFileNameEditor)
            {
                BuildAttributes_FilenameEditor();
            }
            else if (oChoices != null)
            {
                BuildAttributes_CustomChoices();
            }
            else if (oDatasource != null)
            {
                BuildAttributes_ListboxEditor();
            }
            else if (bIsBrowsable)
            {
                BuildAttributes_BrowsableProperty();
            }
        }
		
		#endregion
		
		#region "Private methods"
		
		private void BuildAttributes_FilenameEditor()
		{
			ArrayList attrs = new ArrayList();
			UIFilenameEditor.FileDialogFilterAttribute FilterAttribute = new UIFilenameEditor.FileDialogFilterAttribute(sFilter);
			UIFilenameEditor.SaveFileAttribute SaveDialogAttribute = new UIFilenameEditor.SaveFileAttribute();
			Attribute[] attrArray;
			attrs.Add(FilterAttribute);
			if (eDialogType == UIFilenameEditor.FileDialogType.SaveFileDialog)
			{
				attrs.Add(SaveDialogAttribute);
			}
			attrArray =  (System.Attribute[]) attrs.ToArray(typeof(Attribute));
			oCustomAttributes = new AttributeCollection(attrArray);
		}
		
		private void BuildAttributes_CustomChoices()
		{
			if (oChoices != null)
			{
				CustomChoices.CustomChoicesAttributeList list = new CustomChoices.CustomChoicesAttributeList(oChoices.Items);
				ArrayList attrs = new ArrayList();
				Attribute[] attrArray;
				attrs.Add(list);
				attrArray =  (System.Attribute[]) attrs.ToArray(typeof(Attribute));
				oCustomAttributes = new AttributeCollection(attrArray);
			}
		}
		
		private void BuildAttributes_ListboxEditor()
		{
			if (oDatasource != null)
			{
				UIListboxEditor.UIListboxDatasource ds = new UIListboxEditor.UIListboxDatasource(ref oDatasource);
				UIListboxEditor.UIListboxValueMember vm = new UIListboxEditor.UIListboxValueMember(sValueMember);
				UIListboxEditor.UIListboxDisplayMember dm = new UIListboxEditor.UIListboxDisplayMember(sDisplayMember);
				UIListboxEditor.UIListboxIsDropDownResizable ddr = null;
				ArrayList attrs = new ArrayList();
				attrs.Add(ds);
				attrs.Add(vm);
				attrs.Add(dm);
				if (bIsDropdownResizable)
				{
					ddr = new UIListboxEditor.UIListboxIsDropDownResizable();
					attrs.Add(ddr);
				}
				Attribute[] attrArray;
				attrArray =  (System.Attribute[]) attrs.ToArray(typeof(Attribute));
				oCustomAttributes = new AttributeCollection(attrArray);
			}
		}

        private void BuildAttributes_BrowsableProperty()
        {
            BrowsableTypeConverter.BrowsableLabelStyleAttribute style = new BrowsableTypeConverter.BrowsableLabelStyleAttribute(eBrowsablePropertyLabel);
            oCustomAttributes = new AttributeCollection(new Attribute[] { style });
        }
		
		private void BuildAttributes_CustomEventProperty()
		{
			UICustomEventEditor.DelegateAttribute attr = new UICustomEventEditor.DelegateAttribute(MethodDelegate);
			oCustomAttributes = new AttributeCollection(new Attribute[] {attr});
		}
		
		private object DataColumn
		{
			get
			{
				DataRow oRow = (System.Data.DataRow) oRef;
				if (oRow.RowState != DataRowState.Deleted)
				{
				if (oDatasource == null)
				{
					return oRow[sProp];
				}
				else
				{
					DataTable oLookupTable = oDatasource as DataTable;
					if (oLookupTable != null)
					{
						return oLookupTable.Select(sValueMember + "=" + oRow[sProp])[0][sDisplayMember];
					}
					else
					{
						Information.Err().Raise(Constants.vbObjectError + 513, null, "Bind of DataRow with a DataSource that is not a DataTable is not possible", null, null);
						return null;
					}
				}
			}
				else
				{
					return null;
				}
			}
			set
			{
				DataRow oRow = (System.Data.DataRow) oRef;
				if (oRow.RowState != DataRowState.Deleted)
				{
				if (oDatasource == null)
				{
					oRow[sProp] = value;
				}
				else
				{
					DataTable oLookupTable = oDatasource as DataTable;
					if (oLookupTable != null)
					{
						if (oLookupTable.Columns[sDisplayMember].DataType.Equals(System.Type.GetType("System.String")))
						{
							
							oRow[sProp] = oLookupTable.Select(oLookupTable.Columns[sDisplayMember].ColumnName + " = \'" + value + "\'")[0][sValueMember];
						}
						else
						{
							oRow[sProp] = oLookupTable.Select(oLookupTable.Columns[sDisplayMember].ColumnName + " = " + value)[0][sValueMember];
						}
					}
					else
					{
						Information.Err().Raise(Constants.vbObjectError + 514, null, "Bind of DataRow with a DataSource that is not a DataTable is impossible", null, null);
					}
				}
			}
		}
		}
		
		#endregion
		
		#region "Public properties"

        [Category("Appearance"), DisplayName("Name"), DescriptionAttribute("Display Name of the CustomProperty."), ParenthesizePropertyName(true), XmlElementAttribute("Name")]public string Name
        {
			get
			{
				return sName;
			}
			set
			{
				sName = value;
			}
		}

        [Category("Appearance"), DisplayName("ReadOnly"), DescriptionAttribute("Set read only attribute of the CustomProperty."), XmlElementAttribute("ReadOnly")]public bool IsReadOnly
        {
			get
			{
				return bIsReadOnly;
			}
			set
			{
				bIsReadOnly = value;
			}
		}

        [Category("Appearance"), DescriptionAttribute("Set visibility attribute of the CustomProperty.")]public bool Visible
        {
			get
			{
				return bVisible;
			}
			set
			{
				bVisible = value;
			}
		}

        [Category("Appearance"), DescriptionAttribute("Represent the Value of the CustomProperty.")]public object Value
        {
			get
			{
				if (bRef)
				{
                    if (oRef.GetType() == typeof(DataRow)  || oRef.GetType().IsSubclassOf(typeof(DataRow)))
						return this.DataColumn;
                    else
                        return Interaction.CallByName(oRef, sProp, CallType.Get, null);
				}
				else
				{
					return oValue;
				}
			}
			set
			{
				if (bRef)
				{
					if (oRef.GetType() == typeof(DataRow)  || oRef.GetType().IsSubclassOf(typeof(DataRow)))
							this.DataColumn = value;
                    else
                        Interaction.CallByName(oRef, sProp, CallType.Set, value);
				}
				else
				{
					oValue = value;
				}
			}
		}

        [Category("Appearance"), DescriptionAttribute("Set description associated with the CustomProperty.")]public string Description
        {
			get
			{
				return sDescription;
			}
			set
			{
				sDescription = value;
			}
		}

        [Category("Appearance"), DescriptionAttribute("Set category associated with the CustomProperty.")]public string Category
        {
			get
			{
				return sCategory;
			}
			set
			{
				sCategory = value;
			}
		}

        [XmlIgnore()]public System.Type Type
		{
			get
			{
				if (Value != null)
				{
					return Value.GetType();
				}
				else
				{
					if (oDefaultValue != null)
					{
						return oDefaultValue.GetType();
					}
					else
					{
						return oDefaultType;
					}
				}
            }
		}

        [XmlIgnore()]public AttributeCollection Attributes
		{
			get
			{
				return oCustomAttributes;
			}
			set
			{
				oCustomAttributes = value;
			}
		}

        [Category("Behavior"), DescriptionAttribute("Indicates if the property is browsable or not."), XmlElementAttribute(IsNullable = false)]public bool IsBrowsable
		{
			get
			{
				return bIsBrowsable;
			}
			set
			{
				bIsBrowsable = value;
				if (value == true)
				{
                    BuildAttributes_BrowsableProperty();
                }
			}
		}

		[Category("Appearance"), DisplayName("Parenthesize"), DescriptionAttribute("Indicates whether the name of the associated property is displayed with parentheses in the Properties window."), DefaultValue(false), XmlElementAttribute("Parenthesize")]public bool Parenthesize
		{
			get
			{
				return bParenthesize;
			}
			set
			{
				bParenthesize = value;
			}
		}

        [Category("Behavior"), DescriptionAttribute("Indicates the style of the label when a property is browsable."), XmlElementAttribute(IsNullable = false)]public BrowsableTypeConverter.LabelStyle BrowsableLabelStyle
        {
			get
			{
				return eBrowsablePropertyLabel;
			}
			set
			{
				bool Update = false;
				if (value != eBrowsablePropertyLabel)
				{
					Update = true;
				}
				eBrowsablePropertyLabel = value;
				if (Update)
				{
					BrowsableTypeConverter.BrowsableLabelStyleAttribute style = new BrowsableTypeConverter.BrowsableLabelStyleAttribute(value);
					oCustomAttributes = new AttributeCollection(new Attribute[] {style});
				}
			}
		}

        [Category("Behavior"), DescriptionAttribute("Indicates if the property is masked or not."), XmlElementAttribute(IsNullable = false)]public bool IsPassword
        {
			get
			{
				return bIsPassword;
			}
			set
			{
				bIsPassword = value;
			}
		}

        [Category("Behavior"), DescriptionAttribute("Indicates if the property represents a value in percentage."), XmlElementAttribute(IsNullable = false)]public bool IsPercentage
        {
			get
			{
				return bIsPercentage;
			}
			set
			{
				bIsPercentage = value;
			}
		}

        [Category("Behavior"), DescriptionAttribute("Indicates if the property uses a FileNameEditor converter."), XmlElementAttribute(IsNullable = false)]public bool UseFileNameEditor
        {
			get
			{
				return bUseFileNameEditor;
			}
			set
			{
				bUseFileNameEditor = value;
			}
		}

        [Category("Behavior"), DescriptionAttribute("Apply a filter to FileNameEditor converter."), XmlElementAttribute(IsNullable = false)]public string FileNameFilter
        {
			get
			{
				return sFilter;
			}
			set
			{
				bool UpdateAttributes = false;
				if (value != sFilter)
				{
					UpdateAttributes = true;
				}
				sFilter = value;
				if (UpdateAttributes)
				{
					BuildAttributes_FilenameEditor();
				}
			}
		}

        [Category("Behavior"), DescriptionAttribute("DialogType of the FileNameEditor."), XmlElementAttribute(IsNullable = false)]public UIFilenameEditor.FileDialogType FileNameDialogType
        {
			get
			{
				return eDialogType;
			}
			set
			{
				bool UpdateAttributes = false;
				if (value != eDialogType)
				{
					UpdateAttributes = true;
				}
				eDialogType = value;
				if (UpdateAttributes)
				{
					BuildAttributes_FilenameEditor();
				}
			}
		}

        [Category("Behavior"), DescriptionAttribute("Custom Choices list."), XmlIgnore()]public CustomChoices Choices
        {
			get
			{
				return oChoices;
			}
			set
			{
				oChoices = value;
				BuildAttributes_CustomChoices();
			}
		}

        [Category("Databinding"), XmlIgnore()]public object Datasource
        {
			get
			{
				return oDatasource;
			}
			set
			{
				oDatasource = value;
				BuildAttributes_ListboxEditor();
			}
		}

        [Category("Databinding"), XmlElementAttribute(IsNullable = false)]
        public string ValueMember
		{
			get
			{
				return sValueMember;
			}
			set
			{
				sValueMember = value;
				BuildAttributes_ListboxEditor();
			}
		}

        [Category("Databinding"), XmlElementAttribute(IsNullable = false)]
        public string DisplayMember
		{
			get
			{
				return sDisplayMember;
			}
			set
			{
				sDisplayMember = value;
				BuildAttributes_ListboxEditor();
			}
		}

        [Category("Databinding"), XmlElementAttribute(IsNullable = false)]
        public object SelectedValue
		{
			get
			{
				return oSelectedValue;
			}
			set
			{
				oSelectedValue = value;
			}
		}

        [Category("Databinding"), XmlElementAttribute(IsNullable = false)]
        public object SelectedItem
		{
			get
			{
				return oSelectedItem;
			}
			set
			{
				oSelectedItem = value;
			}
		}

        [Category("Databinding"), XmlElementAttribute(IsNullable = false)]
        public bool IsDropdownResizable
		{
			get
			{
				return bIsDropdownResizable;
			}
			set
			{
				bIsDropdownResizable = value;
				BuildAttributes_ListboxEditor();
			}
		}

        [XmlIgnore()]public UITypeEditor CustomEditor
		{
			get
			{
				return oCustomEditor;
			}
			set
			{
				oCustomEditor = value;
			}
		}

        [XmlIgnore()]public TypeConverter CustomTypeConverter
		{
			get
			{
				return oCustomTypeConverter;
			}
			set
			{
				oCustomTypeConverter = value;
			}
		}
				
		[XmlIgnore()]public object Tag
		{
			get
			{
				return oTag;
			}
			set
			{
				oTag = value;
			}
		}
		
		[XmlIgnore()]public object DefaultValue
		{
			get
			{
				return oDefaultValue;
			}
			set
			{
				oDefaultValue = value;
			}
		}
		
		[XmlIgnore()]public Type DefaultType
		{
			get
			{
				return oDefaultType;
			}
			set
			{
				oDefaultType = value;
			}
		}
		
		[XmlIgnore()]public UICustomEventEditor.OnClick OnClick
		{
			get
			{
				return MethodDelegate;
			}
			set
			{
				MethodDelegate = value;
				BuildAttributes_CustomEventProperty();
			}
		}
		
		#endregion
		
		#region "CustomPropertyDescriptor"
		public class CustomPropertyDescriptor : PropertyDescriptor
		{
			
			protected CustomProperty oCustomProperty;
			
			public CustomPropertyDescriptor(CustomProperty myProperty, Attribute[] attrs) : base(myProperty.Name, attrs)
			{
				if (myProperty == null)
				{
					oCustomProperty = null;
				}
				else
				{
					
					oCustomProperty = myProperty;
				}
			}
			
			public override bool CanResetValue(object component)
			{
				if ((oCustomProperty.DefaultValue != null)|| (oCustomProperty.DefaultType != null))
				{
					return true;
				}
				else
				{
					return false;
				}
			}
			
			public override System.Type ComponentType
			{
				get
				{
					return this.GetType();
				}
			}
			
			public override object GetValue(object component)
			{
				return oCustomProperty.Value;
			}
			
			public override bool IsReadOnly
			{
				get
				{
					return oCustomProperty.IsReadOnly;
				}
			}
			
			public override System.Type PropertyType
			{
				get
				{
					return oCustomProperty.Type;
				}
			}
			
			public override void ResetValue(object component)
			{
				oCustomProperty.Value = oCustomProperty.DefaultValue;
				this.OnValueChanged(component, EventArgs.Empty);
			}
			
			public override void SetValue(object component, object value)
			{
				oCustomProperty.Value = value;
				this.OnValueChanged(component, EventArgs.Empty);
			}
			
			public override bool ShouldSerializeValue(object component)
			{
				object oValue = oCustomProperty.Value;
				if ((oCustomProperty.DefaultValue != null)&& (oValue != null))
				{
					return ! oValue.Equals(oCustomProperty.DefaultValue);
				}
				else
				{
					return false;
				}
			}
			
			public override string Description
			{
				get
				{
					return oCustomProperty.Description;
				}
			}
			
			public override string Category
			{
				get
				{
					return oCustomProperty.Category;
				}
			}
			
			public override string DisplayName
			{
				get
				{
					return oCustomProperty.Name;
				}
			}
			
			public override bool IsBrowsable
			{
				get
				{
					return oCustomProperty.IsBrowsable;
				}
			}
			
			public object CustomProperty
			{
				get
				{
					return oCustomProperty;
				}
			}
		}
		#endregion		
	}	
}

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 MIT License


Written By
Software Developer (Senior)
United States United States
AKA Rich Insley.

I have over 25 years experience in programming, and I'm completely self taught. (Except for one year at California State University Fresno where I had to learn the God awful language Miranda (http://miranda.org.uk/). I've spent 10 years as a Paratrooper in the US Army during the Clinton Administration.

Comments and Discussions