Click here to Skip to main content
15,881,709 members
Articles / Desktop Programming / WPF

ObjectPresenter - How to Generate an Object's Testing GUI from a Given Object

Rate me:
Please Sign up or sign in to vote.
4.94/5 (27 votes)
5 Jan 2012CPOL11 min read 37.2K   924   49  
In this article, I explain step by step, how we can create a WPF custom control that gets an object and, generates a GUI that enables editing that object's properties and invoking that object's methods.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows;

namespace ObjectPresentation
{
    public class ValuePresenter : Control
    {
        static ValuePresenter()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(ValuePresenter), new FrameworkPropertyMetadata(typeof(ValuePresenter)));
        }

        private bool _ignorePresentedValueChanges;
        private bool _ignoreValueChanges;

        #region Properties

        #region ValueType
        public Type ValueType
        {
            get { return (Type)GetValue(ValueTypeProperty); }
            set { SetValue(ValueTypeProperty, value); }
        }

        public static readonly DependencyProperty ValueTypeProperty =
            DependencyProperty.Register("ValueType", typeof(Type), typeof(ValuePresenter), new UIPropertyMetadata(null, OnValueTypeChanged));

        private static void OnValueTypeChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            ValuePresenter vp = sender as ValuePresenter;
            if (vp == null)
            {
                return;
            }

            InputValueViewModel presentedValue = new InputValueViewModel
            {
                ValueType = vp.ValueType,
                KnownTypes = vp.KnownTypes,
                AutoGenerateCompatibleTypes = vp.AutoGenerateCompatibleTypes,
                DataTemplates = vp.DataTemplates
            };

            presentedValue.PropertyChanged += (s1, e1) =>
            {
                if (vp._ignorePresentedValueChanges)
                {
                    return;
                }

                if (e1.PropertyName == "Value")
                {
                    vp._ignoreValueChanges = true;
                    vp.Value = vp.PresentedValue.Value;
                    vp._ignoreValueChanges = false;
                }
            };

            vp.PresentedValue = presentedValue;
        }
        #endregion

        #region PresentedValue
        public InputValueViewModel PresentedValue
        {
            get { return (InputValueViewModel)GetValue(PresentedValueProperty); }
            protected set { SetValue(PresentedValueProperty, value); }
        }

        public static readonly DependencyProperty PresentedValueProperty =
            DependencyProperty.Register("PresentedValue", typeof(InputValueViewModel), typeof(ValuePresenter), new UIPropertyMetadata(null, OnPresentedValueChanged));

        private static void OnPresentedValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            ValuePresenter vp = sender as ValuePresenter;
            if (vp == null)
            {
                return;
            }

            if (vp._ignorePresentedValueChanges)
            {
                return;
            }

            if (vp.PresentedValue != null)
            {
                vp._ignoreValueChanges = true;
                vp.Value = vp.PresentedValue.Value;
                vp._ignoreValueChanges = false;
            }
        }
        #endregion

        #region Value
        public object Value
        {
            get { return (object)GetValue(ValueProperty); }
            set { SetValue(ValueProperty, value); }
        }

        public static readonly DependencyProperty ValueProperty =
            DependencyProperty.Register("Value", typeof(object), typeof(ValuePresenter), new UIPropertyMetadata(null, OnValueChanged));

        private static void OnValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            ValuePresenter vp = sender as ValuePresenter;
            if (vp == null)
            {
                return;
            }

            if (vp._ignoreValueChanges)
            {
                return;
            }

            vp._ignorePresentedValueChanges = true;

            if (vp.ValueType == null)
            {
                vp.ValueType = vp.Value != null ? vp.Value.GetType() : null;
            }

            vp.PresentedValue.Value = vp.Value;

            vp._ignorePresentedValueChanges = false;
        }
        #endregion

        #region KnownTypes
        public IEnumerable<Type> KnownTypes
        {
            get { return (IEnumerable<Type>)GetValue(KnownTypesProperty); }
            set { SetValue(KnownTypesProperty, value); }
        }

        public static readonly DependencyProperty KnownTypesProperty =
            DependencyProperty.Register("KnownTypes", typeof(IEnumerable<Type>), typeof(ValuePresenter), new UIPropertyMetadata(null, OnKnownTypesChanged));

        private static void OnKnownTypesChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            ValuePresenter vp = sender as ValuePresenter;
            if (vp == null)
            {
                return;
            }

            if (vp.PresentedValue != null)
            {
                vp.PresentedValue.KnownTypes = vp.KnownTypes;
            }
        }
        #endregion

        #region AutoGenerateCompatibleTypes
        public bool AutoGenerateCompatibleTypes
        {
            get { return (bool)GetValue(AutoGenerateCompatibleTypesProperty); }
            set { SetValue(AutoGenerateCompatibleTypesProperty, value); }
        }

        public static readonly DependencyProperty AutoGenerateCompatibleTypesProperty =
            DependencyProperty.Register("AutoGenerateCompatibleTypes", typeof(bool), typeof(ValuePresenter), new UIPropertyMetadata(true, OnAutoGenerateCompatibleTypesChanged));

        private static void OnAutoGenerateCompatibleTypesChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            ValuePresenter vp = sender as ValuePresenter;
            if (vp == null)
            {
                return;
            }

            if (vp.PresentedValue != null)
            {
                vp.PresentedValue.AutoGenerateCompatibleTypes = vp.AutoGenerateCompatibleTypes;
            }
        }
        #endregion

        #region DataTemplates
        public IEnumerable<TypeDataTemplate> DataTemplates
        {
            get { return (IEnumerable<TypeDataTemplate>)GetValue(DataTemplatesProperty); }
            set { SetValue(DataTemplatesProperty, value); }
        }

        public static readonly DependencyProperty DataTemplatesProperty =
            DependencyProperty.Register("DataTemplates", typeof(IEnumerable<TypeDataTemplate>), typeof(ValuePresenter), new UIPropertyMetadata(null, OnDataTemplatesChanged));

        private static void OnDataTemplatesChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            ValuePresenter vp = sender as ValuePresenter;
            if (vp == null)
            {
                return;
            }

            if (vp.PresentedValue != null)
            {
                vp.PresentedValue.DataTemplates = vp.DataTemplates;
            }
        }

        #endregion

        #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 Code Project Open License (CPOL)


Written By
Software Developer
Israel Israel
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions