Skip to content

Instantly share code, notes, and snippets.

@brinko99
Created February 8, 2018 22:09
Show Gist options
  • Save brinko99/e242b79f4eaec30e834c6d3db2bd17d6 to your computer and use it in GitHub Desktop.
Save brinko99/e242b79f4eaec30e834c6d3db2bd17d6 to your computer and use it in GitHub Desktop.
.NET WPF Binding markup extension supporting designer specific value
using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Data;
using System.Windows.Markup;
using static System.Convert;
namespace MarkupExtensions
{
/// <summary>
/// Markup extension that provides a binding that supports designer specific value.
/// </summary>
/// <remarks>
/// The binding is used in place of a typical binding. Within the designer, the specified <see cref="DesignTimeValue"/> will be used
/// instead of the binding specified.
/// <p/>
/// Typically simple values are passed into the extension as strings. <see cref="DesignTimeValueType"/> can specify a type to which to
/// convert the value through <see cref="ChangeType(object, TypeCode)"/>.
/// <p/>
/// Concept borrowed from: <see href="https://stackoverflow.com/a/38011434/84522"/>
/// </remarks>
/// <example>
/// <code><![CDATA[
/// <RowDefinition MaxHeight="{cm:BindingWithDesignSupport
/// {Binding ElementName = RealTimeView, Path = ActualHeight, Mode = OneTime},
/// DesignTimeValue=300, DesignTimeValueType={x:Type sys:Double}}"/>
/// ]]></code>
/// </example>
/// <seealso cref="MarkupExtension" />
public class BindingWithDesignSupport : MarkupExtension
{
private static readonly bool IsInDesignMode = DesignerProperties.GetIsInDesignMode(new DependencyObject());
private readonly object _unsetObject = new object();
/// <summary>
/// Initializes a new instance of the <see cref="BindingWithDesignSupport" /> class.
/// </summary>
public BindingWithDesignSupport()
{
DesignTimeValue = _unsetObject;
}
/// <summary>
/// Initializes a new instance of the <see cref="BindingWithDesignSupport" /> class.
/// </summary>
/// <param name="binding">The binding.</param>
public BindingWithDesignSupport(BindingBase binding)
: this()
{
Binding = binding ?? throw new ArgumentNullException(nameof(binding));
}
/// <summary>
/// Gets or sets the binding (required).
/// </summary>
public BindingBase Binding { get; set; }
/// <summary>
/// Gets or sets the design time value (required).
/// </summary>
public object DesignTimeValue { get; set; }
/// <summary>
/// Gets or sets the type of the design time value (optional).
/// </summary>
public Type DesignTimeValueType { get; set; }
/// <inheritdoc />
/// <param name="serviceProvider">The parameter is not used.</param>
public override object ProvideValue(IServiceProvider serviceProvider)
{
if (Binding == null)
{
throw new InvalidOperationException($"Required property '{nameof(Binding)}' is unset.");
}
if (DesignTimeValue == _unsetObject)
{
throw new InvalidOperationException($"Required property '{nameof(DesignTimeValue)}' is unset.");
}
if (DesignTimeValueType != null)
{
DesignTimeValue = ChangeType(DesignTimeValue, DesignTimeValueType);
}
return IsInDesignMode ? DesignTimeValue : Binding.ProvideValue(serviceProvider);
}
}
}
@brinko99
Copy link
Author

brinko99 commented Feb 8, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment