|
using System;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
using Pfz.DataTypes;
using Pfz.Ranges;
namespace Pfz.WpfControls
{
/// <summary>
/// Control used to edit ranges. It displays a slider and a text-box for editing
/// values.
/// </summary>
/// <typeparam name="TRange">The type of the range used.</typeparam>
public class RangeControl<TRange>:
Grid,
IValueControl,
IValueContainer<TRange>
where
TRange: IRange
{
private Slider fSlider = new Slider();
private TextBox fTextBox = new TextBox();
internal ColumnDefinition fTextBoxColumn;
private static readonly Type fPropertyDataType;
private static readonly ConstructorInfo fRangeConstructor;
/// <summary>
/// Gets some information for the Range type only once.
/// </summary>
static RangeControl()
{
var propertyType = typeof(TRange);
while(propertyType != null)
{
if (propertyType.IsGenericType)
{
if (propertyType.GetGenericTypeDefinition() == typeof(Range<>))
{
Type dataType = propertyType.GetGenericArguments()[0];
fPropertyDataType = dataType;
fRangeConstructor = typeof(TRange).GetConstructor(new Type[]{dataType});
return;
}
}
propertyType = propertyType.BaseType;
}
throw new ApplicationException("Can't find the Range constructor.");
}
/// <summary>
/// Creates a new RangeControl.
/// </summary>
public RangeControl()
{
ColumnDefinition columnSlider = new ColumnDefinition();
columnSlider.Width = new GridLength(1, GridUnitType.Star);
ColumnDefinitions.Add(columnSlider);
ColumnDefinition columnTextBox = new ColumnDefinition();
columnTextBox.Width = new GridLength(100, GridUnitType.Pixel);
ColumnDefinitions.Add(columnTextBox);
fTextBoxColumn = columnTextBox;
RowDefinition row = new RowDefinition();
row.Height = new GridLength(1, GridUnitType.Star);
RowDefinitions.Add(row);
Children.Add(fSlider);
Children.Add(fTextBox);
Grid.SetColumn(fSlider, 0);
Grid.SetRow(fSlider, 0);
Grid.SetColumn(fTextBox, 1);
Grid.SetRow(fTextBox, 0);
fSlider.ValueChanged += fSlider_ValueChanged;
fTextBox.LostFocus += fTextBox_LostFocus;
var attribute = Range.GetRangeAttribute(typeof(TRange));
fSlider.Minimum = Convert.ToDouble(attribute.MinimumValue);
fSlider.Maximum = Convert.ToDouble(attribute.MaximumValue);
p_GetSliderValue();
}
void fTextBox_LostFocus(object sender, RoutedEventArgs e)
{
try
{
double result;
if (double.TryParse(fTextBox.Text, out result))
fSlider.Value = result;
else
p_GetSliderValue();
}
catch
{
p_GetSliderValue();
}
}
void fSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
p_GetSliderValue();
}
private void p_GetSliderValue()
{
var dataType = fPropertyDataType;
if (dataType == null)
{
fTextBox.Text = fSlider.Value.ToString();
return;
}
object value = Convert.ChangeType(fSlider.Value, dataType);
fTextBox.Text = value.ToString();
}
/// <summary>
/// Clears the value of this control.
/// </summary>
public void Clear()
{
fSlider.Value = fSlider.Minimum;
}
/// <summary>
/// Gets or sets a value indicating that this control should be read-only.
/// </summary>
public bool IsReadOnly
{
get
{
return !IsEnabled;
}
set
{
IsEnabled = !value;
}
}
/// <summary>
/// Gets or sets the range value.
/// </summary>
public TRange Value
{
get
{
var value = fSlider.Value;
var typedValue = Convert.ChangeType(value, fPropertyDataType);
var range = fRangeConstructor.Invoke(new object[]{typedValue});
return (TRange)range;
}
set
{
if (value == null)
fSlider.Value = 0;
else
fSlider.Value = Convert.ToDouble(value.Value);
}
}
#region IValueContainer Members
object IValueContainer.Value
{
get
{
return Value;
}
set
{
Value = (TRange)value;
}
}
#endregion
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
I started to program computers when I was 11 years old, as a hobbyist, programming in AMOS Basic and Blitz Basic for Amiga.
At 12 I had my first try with assembler, but it was too difficult at the time. Then, in the same year, I learned C and, after learning C, I was finally able to learn assembler (for Motorola 680x0).
Not sure, but probably between 12 and 13, I started to learn C++. I always programmed "in an object oriented way", but using function pointers instead of virtual methods.
At 15 I started to learn Pascal at school and to use Delphi. At 16 I started my first internship (using Delphi). At 18 I started to work professionally using C++ and since then I've developed my programming skills as a professional developer in C++ and C#, generally creating libraries that help other developers do their work easier, faster and with less errors.
Want more info or simply want to contact me?
Take a look at:
http://paulozemek.azurewebsites.net/
Or e-mail me at: paulozemek@outlook.com
Codeproject MVP 2012, 2015 & 2016
Microsoft MVP 2013-2014 (in October 2014 I started working at Microsoft, so I can't be a Microsoft MVP anymore).