Smallfish

Tips, Tricks, Shticks & Anything That Can Help You Be better Developer

April 2009 - Posts

How To Create XAML Markup Extension in WPF – Creating the Now markup extension

What?

Display a label and analog clock on screen, they should be updated “live” with the time.

How?

I use XAML Markup Extension for several reasons:

  1. It makes it easy to use it on XAML, especially to bind to it.
  2. Learn the framework extension points.
  3. Reuse – easy to use it everywhere with half line of XAML.

Show me the money!

    /// <summary>
    /// XAML Markup Extension to bind dependency property (DateTime or String)
    /// to the current date and time (updated each second)
    /// </summary>
    public class NowExtension : MarkupExtension
    {
        #region State
 
        // default, full date format (current culture)
        private readonly string m_format = 
            CultureInfo.CurrentCulture.DateTimeFormat.FullDateTimePattern;
        // for empty constructor we return the DateTime
        private readonly bool m_returnDate = false;
 
        private DependencyObject m_targetObject;
        private DependencyProperty m_targetProperty;
        private DispatcherTimer m_timer;
 
        #endregion
        #region Constructors
 
        /// <summary>
        /// Create new Now Extension that return the 
        /// current DateTime (DateTime.Now)
        /// </summary>
        public NowExtension()
        {
            m_returnDate = true;
        }
 
        /// <summary>
        /// Create new Now Extension that return the 
        /// current DateTime formatted (calling ToString 
        /// with m_format)
        /// </summary>
        public NowExtension(string format)
        {
            if (!string.IsNullOrEmpty(format))
            {
                m_format = format;
            }
        }
 
        #endregion
 
        /// <summary>
        /// Overrides MarkupExtension.ProvideValue to return 
        /// the current datetime and hook a timer to update the 
        /// target propery each second 
        /// (using DispatcherTime with Background priority)
        /// </summary>
        /// <param name="serviceProvider"></param>
        /// <returns></returns>
        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            var targetHelper = 
                (IProvideValueTarget)
                serviceProvider.GetService(typeof(IProvideValueTarget));
 
            m_targetObject = 
                targetHelper.TargetObject as DependencyObject;
 
            m_targetProperty = 
                targetHelper.TargetProperty as DependencyProperty;
 
            m_timer = new DispatcherTimer(DispatcherPriority.Background);
            m_timer.Interval = TimeSpan.FromSeconds(1);
            m_timer.Tick += new EventHandler(m_timer_Tick);
            m_timer.Start();
 
            if (m_returnDate)
            {
                return DateTime.Now;
            }
 
            return GetNowValue();
        }
 
        protected virtual string GetNowValue()
        {
            return DateTime.Now.ToString(m_format);
        }
 
        void m_timer_Tick(object sender, EventArgs e)
        {
            if (m_targetObject != null && m_targetProperty != null)
            {
                object value = GetNowValue();
                if (m_returnDate)
                {
                    value = DateTime.Now;
                }
                m_targetObject.SetValue(m_targetProperty, value);
            }
        }
    }

How does it works?

The first time the ProviderValue is called, we are hooking to the target DependencyObject / DependencyProperty so we will be able to set the property on timer intervals. Then we start a timer (with interval of 1 second) and in that timer Tick event we set the new value to the hooked property, the last line just return the current value for the first time.

Posted: Apr 19 2009, 08:46 AM by Yair Cohen | with 1 comment(s)
תגים:, , ,
How To Get A Property Name Using Lambda Expression in C# 3.0

During development of WPF application using M-V-VM design pattern (by Josh Smith on MSDN Mag.) I came across a problem of refactoring the view model classes, especially the properties’ names. The view model classes are implementing the INotifyPropertyChanged interface by inheriting from a helper NotifyPropertyChanged base class which have a method to raise the property changed event called ‘SendPropertyChanged’. That method gets “propertyName” parameter which is a string, and this was the problem:

My view model properties looks like:

        private string m_name;
        public string Name
        {
            get 
            {
                return m_name;
            }
            set
            {
                if (m_name != value)
                {
                    m_name = value;
                    SendPropertyChanged("Name");
                }
            }
        }

the problem here is if I change the property name to “CustomerName” I must ensure to correct the string name in the method parameter. Even worse, if for some reason another method / property is calling ‘SendPropertyChanged’ for the ‘Name’ property it will cause invisible problems (you will see it on the screen, but very difficult to spot). And then:

Lambda Expression to the rescue!

What I wanted to achieve is:

        private string m_name;
        public string Name
        {
            get 
            {
                return m_name;
            }
            set
            {
                if (m_name != value)
                {
                    m_name = value;
                    SendPropertyChanged(()=> this.Name);
                }
            }
        }

Note the bolded “() => this.Name”, this will ensure that if anyone changes the name of the property the build will fail (or, using the Refactoring->Rename in VS will change it automatically). After a lot of searches I found the way to do this (in Bernardo Heynemann blog post):

        private string GetPropertyName<T>(Expression<Func<T>> property)
        {
            var propertyInfo = (property.Body as MemberExpression).Member as PropertyInfo;
            if (propertyInfo == null)
            {
                throw new ArgumentException("The lambda expression 'property' 
should point to a valid Property");
            }
 
            var propertyName = propertyInfo.Name;
 
            return propertyName;
        }

Note the parameter type Expression<Func<T>> – whenever you cast a delegate (in this case of Func<T>) into Expression you are getting the associated Expression Tree and not the delegate itself. The call is clean and nice due to another feature of C# 3.0 ‘Type inference’ the compiler determines the type of T parameter and does not require us to add the ugly curly brackets.

Enjoy the new revolution!