Skip to content

Instantly share code, notes, and snippets.

@cuppster
Last active August 29, 2015 14:03
Show Gist options
  • Save cuppster/b4065d4d0377a739c622 to your computer and use it in GitHub Desktop.
Save cuppster/b4065d4d0377a739c622 to your computer and use it in GitHub Desktop.
Technique using a binding converter to return an object representing viewmodel state for displaying an adorner.
using System;
using System.Globalization;
using System.Windows.Data;
namespace WpfApplication1
{
/*
see: http://cuppster.com/2014/07/10/using-the-state-pattern-for-adorning-in-xaml/
<!-- in resources ... -->
<local:FooStateConverter x:Key="FooStateConverter" />
<!-- data template for a specific state -->
<DataTemplate DataType="{x:Type local:FooStateDefaultAdorner}">
<Canvas>
<Image Source="/Images/DefaultOverlay.png" Canvas.Left="5" Canvas.Top="5"/>
</Canvas>
</DataTemplate>
...
<!-- inside the data template for the view model for Foo -->
<Grid>
<Image Source="/Images/FooBaseImage.png"/>
<AdornerDecorator>
<ContentControl Content="{Binding Converter={StaticResource FooStateConverter}}"/>
</AdornerDecorator>
*/
public class FooState
{
// a base class is convient so that the generic state class
// can be more type-safe and return a known base class instead of 'object'
}
public class FooState<T> : FooState
{
// each generic class declared will recieve its own _instance static member
// ... that's the trick
private static FooState _instance;
public FooState()
{
_instance = this;
}
public new static Type GetType()
{
// returns the type of the generic parameter NOT of this class
return typeof(T);
}
public static FooState Instance
{
get
{
if (null == _instance)
{
Type t = GetType();
Activator.CreateInstance(t);
}
return _instance;
}
}
}
public class FooStateDefaultAdorner : FooState<FooStateDefaultAdorner>
{
// use a XAML DataTemplate to present this object
}
public class FooStateInvalidAdorner : FooState<FooStateInvalidAdorner>
{
// use a XAML DataTemplate to present this object
}
public class FooStateConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
// Inspect viewmodel or model for state
// and create the appropriate FooState class
/*
1. cast 'value' to your view model class
2. query the state of the view model
3. return a specific FooState instance based on that state
e.g.
var myViewModel = object as MyViewModel;
if (myViewModel.IsDefault)
return FooStateDefaultAdorner.Instance;
else if (myViewModel.IsInvalid)
return FooStateInvalidAdorner.Instance;
*/
// fall-through...
return null;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return null;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment