Bidirectional control
In these modern times dashboards aren't just about displaying information, oh no,
they're about gathering and manipulating it too. Certain controls in the collection
support bidirectional operation.
To make a control by directional you set the IsBidirectionalFlag to true and the
ShowFocus property as required
<db:DiamondSlider IsBidirectional="True" ShowFocus="True" Width="125" />
Which gives the following operation (mouse over the diamond and drag it to set the
value)
Currently the following controls can operate in a bidirectional manner (change any slider
and the others will update through a TwoWay databinding)
You can deal with the value changing in one of two easy ways, through events, or
through two way data binding. Lets deal with events first.
Event driven action
The Dashboard base class fires the Value changed event when the value
changes (not a trick name then, is it?). Let's register an event on our slider
<StackPanel Orientation="Horizontal">
<TextBlock x:Name="_t" Text="000 -> 000" VerticalAlignment="Center"
TextAlignment="Right" Width="70" Foreground="AntiqueWhite"/>
<db:DiamondSlider Value="50" IsBidirectional="True" ShowFocus="True"
ValueChanged="DiamondSlider_ValueChanged" x:Name="_ds"/>
</StackPanel>
And in the code behind we handle the event and show the values in a message box
private void DiamondSlider_ValueChanged(object sender, DashboardValueChangedEventArgs e)
{
if (_t != null)
{
_t.Text = String.Format("{0} -> {1} ", e.OldValue, e.NewValue);
}
}
The value changed event is fired when the value is initialized in XAML. At
this point the local variable _t has not been set to point to the text block. So
we test for null to catch this case. I am investigating if there is a flag
supported by the runtime to determine if we are initializing from XAML or not.
Here it is our example running live
Two way data binding
In this example we are going to tie a text block and a slider together using data bindings. The text block will data
bind its text property to the CurrentValue propert of its DataContext in a one way manner. The Slider will bind its value property to
the same property but in a two way mode. Updates to the slider will be placed in the object and reflected in the TextBlock without
any explicit event handling.
Here is the XAML
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding CurrentValue}" VerticalAlignment="Center"
TextAlignment="Right" Width="40" Foreground="AntiqueWhite"/>
<db:DiamondSlider Value="{Binding CurrentValue, Mode=TwoWay}" IsBidirectional="True" ShowFocus="True" />
<Button Content="Set To 50" Click="Button_Click"/>
</StackPanel>
In the code behind we initialize the DataContext of the control to an instance of a class that implements INotifyPropertyChange
/// <summary>
/// Class used to demonstrate two way data binding
/// </summary>
public partial class BiDiamond3 : UserControl
{
public BiDiamond3()
{
InitializeComponent();
BoundObject bo = new BoundObject { CurrentValue = 25 };
DataContext = bo;
}
/// <summary>
/// Show we are two way
/// </summary>
private void Button_Click(object sender, RoutedEventArgs e)
{
BoundObject bo = DataContext as BoundObject;
bo.CurrentValue = 50;
}
}
/// <summary>
/// Class to do an example binding
/// </summary>
public class BoundObject : INotifyPropertyChanged
{
private double _currentValue;
/// <summary>
/// Current vlaue property, raises the on property changed event
/// </summary>
public double CurrentValue
{
get { return _currentValue; }
set
{
_currentValue = value;
OnPropertyChanged("CurrentValue");
}
}
#region INotifyPropertyChanged Members
/// <summary>
/// One of my properties has changed
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Notify any listeners that a property has changed
/// </summary>
/// <param name="propName">Name of the property</param>
protected virtual void OnPropertyChanged(string propName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
#endregion
}
Which gives us a similar result to before but with a better feel. Click the button to set the value to 50 and see two way binding in action, Neat :-)