In this post, I briefly discuss the design behind the VisibilityControl
.
Posts in this series:
If you look at the source code history at codeplex, you will notice that I first designed this control with two dependency properties, one for the true content and one for the false content. The resulting XAML that the user needed to enter to use the control seems a bit clunky to me. Therefore, I switched to an ItemsControl-derived solution. I ask the user of the control to load the Items property with the false and true content respectively.
It does seem a bit weird to use a list to hold two and only two items, but there you have it. Maybe someday I can shore-up the sanity of this choice by making the control be able to display one of a series of items based upon the value of an
int
, enum
, or string
.
The only real thing to notice about the source below is to understand that we set the value of the dependency property called
VisibleContentto
the appropriate user interface element found in the list, based upon the value of
IsTrue
. The default style simply shows the content of VisibleContent
.
VisibilityControl.cs
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Markup;
namespace VisibilityControlLibrary
{
[ContentProperty(Name = "Items")]
public class VisibilityControl : ItemsControl
{
public VisibilityControl()
{
this.DefaultStyleKey = typeof(VisibilityControl);
Items.VectorChanged += OnItemsChanged;
}
public bool IsTrue
{
get { return (bool)GetValue(IsTrueProperty); }
set { SetValue(IsTrueProperty, value); }
}
public static readonly DependencyProperty IsTrueProperty =
DependencyProperty.Register("IsTrue", typeof(bool),
typeof(VisibilityControl), new PropertyMetadata(null, OnIsTrueChanged));
public object VisibleContent
{
get { return (object)GetValue(VisibleContentProperty); }
private set { SetValue(VisibleContentProperty, value); }
}
public static readonly DependencyProperty VisibleContentProperty =
DependencyProperty.Register("VisibleContent", typeof(object),
typeof(VisibilityControl), new PropertyMetadata(null));
private static void OnIsTrueChanged(DependencyObject d, DependencyPropertyChangedEventArgs args)
{
var visibilityItemsControl = d as VisibilityControl;
if (visibilityItemsControl != null)
{
visibilityItemsControl.Evaluate();
}
}
void OnItemsChanged(IObservableVector<object> sender, IVectorChangedEventArgs evt)
{
Evaluate();
}
void Evaluate()
{
if (Items.Count >= 2)
{
VisibleContent = Items[IsTrue ? 1 : 0];
}
else
{
VisibleContent = null;
}
}
}
}
Generic.xaml
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:VisibilityControlLibrary">
<Style
TargetType="local:VisibilityControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:VisibilityControl">
<Grid>
<ContentPresenter
Content="{TemplateBinding VisibleContent}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>