Slider user control with float values - c#

The float word I think is inappropriate but...
I try to make a custom slider control and seems to work fine but for some reason for some values the control crashes.
For example if I choose Maximum value = 1.112 the slider show maximum 1.111 and if I increase the value with numeric Up Down I get this error:
System Argument Out Of Range Exception H Result = 0x80131502
Message=Value of '1112' is not valid for 'Value'. 'Value' should be
between 'Minimum' and 'Maximum'.
using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
namespace UserSliderControl
{
//set the default event for this user control
[DefaultEvent("ValueChanged")]
public partial class SliderControl : UserControl
{
//set the initial values
private int multiplier = 1;
private float minimum = 0f;
private float maximum = 100f;
private int decimalPlaces = 0;
private float _value = 0f;
private float resetvalue = 0f;
private int largeChange = 5;
private Image buttonResetImage = null;
private Color controlNameForeColor = SystemColors.WindowText;
//set the event handler for this user control = ValueChanged
public event EventHandler ValueChanged;
//set the properties for this user control
#region properties
public string ControlName
{
get { return labelControlName.Text; }
set
{
labelControlName.Text = value;
}
}
public Color ControlNameForeColor
{
get { return controlNameForeColor; }
set
{
controlNameForeColor = value;
labelControlName.ForeColor = controlNameForeColor;
}
}
public Image ButtonResetImage
{
get { return buttonResetImage; }
set
{
buttonResetImage = value;
btnReset.BackgroundImage = buttonResetImage;
btnReset.BackgroundImageLayout = ImageLayout.Zoom;
}
}
public float Value
{
get { return _value; }
set
{
_value = value;
if (_value > maximum) _value = maximum;
if (_value < minimum) _value = minimum;
NumericUpDown.Value = (decimal)_value;
}
}
public float ResetValue
{
get { return resetvalue; }
set
{
resetvalue = value;
if (resetvalue > maximum) resetvalue = maximum / 2;
if (resetvalue < minimum) resetvalue = minimum;
}
}
public float Maximum
{
get { return maximum; }
set
{
maximum = value;
if (maximum < minimum)
{
maximum = 2 * minimum;
}
TrackBar.Maximum = (int)(maximum * multiplier);
NumericUpDown.Maximum = (decimal)maximum;
}
}
public float Minimum
{
get { return minimum; }
set
{
minimum = value;
if (minimum > maximum)
{
minimum = 0;
}
TrackBar.Minimum = (int)minimum * multiplier;
NumericUpDown.Minimum = (int)minimum;
}
}
public int DecimalPlaces
{
get { return decimalPlaces; }
set
{
decimalPlaces = value;
if (decimalPlaces > 3)
{
decimalPlaces = 3;
}
multiplier = (int)Math.Pow(10, decimalPlaces);
NumericUpDown.DecimalPlaces = decimalPlaces;
NumericUpDown.Increment = 1m / multiplier;
}
}
public int LargeChange
{
get { return largeChange; }
set
{
largeChange = value;
TrackBar.LargeChange = largeChange;
}
}
#endregion
public SliderControl()
{
InitializeComponent();
}
private void TrackBar_Scroll(object sender, EventArgs e)
{
NumericUpDown.Value = (decimal)TrackBar.Value / multiplier;
Value = (float)TrackBar.Value / multiplier;
OnValueChanged();
}
private void NumericUpDown_ValueChanged(object sender, EventArgs e)
{
TrackBar.Value = (int)(NumericUpDown.Value * multiplier);
Value = (float)NumericUpDown.Value;
OnValueChanged();
}
private void btnReset_Click(object sender, EventArgs e)
{
NumericUpDown.Value = (decimal)ResetValue;
TrackBar.Focus();
OnValueChanged();
}
protected virtual void OnValueChanged()
{
ValueChanged?.Invoke(this, EventArgs.Empty);
}
}
}

Related

How can I get and set the Range attribute min and max?

[Range(-3, 3)]
public float range;
I want later in the code to do something like :
range.min = 2
range.max = 20;
Or get
int min = range.min;
int max = range.max;
You can't change an attribute's state at runtime, but you can read it using reflection:
class YourClass
{
[Range(-3, 3)]
public float range;
}
var range = typeof(YourClass)
.GetField(nameof(YourClass.range))
.GetCustomAttribute<RangeAttribute>();
float min = range.min;
float max = range.max;
Based on: https://github.com/jamesjlinden/unity-decompiled/blob/master/UnityEngine/UnityEngine/RangeAttribute.cs
Can you change it to an object like below?
public class range
{
private float _value;
public range(int min, int max)
{
Min = min;
Max = max;
}
public float Value
{
get
{
return _value;
}
set
{
if (value > Max || value < Min) throw new Exception("value out of
range.");
_value = value;
}
}
public int Min { get; }
public int Max { get; }
}
use it like;
rangeObj = new range(-3,3);
rangeObj.Min
rangeObj.Max
rangeObj.Value

How to Create bigger CheckBox

I want to design above screen in windows forms. When I am tried to use checkbox control the size of the box is not increasing.
I tried below code but checkbox color and bored color is not changing.
using System;
using System.Drawing;
using System.Windows.Forms;
class MyCheckBox : CheckBox {
public MyCheckBox() {
this.TextAlign = ContentAlignment.MiddleRight;
}
public override bool AutoSize {
get { return base.AutoSize; }
set { base.AutoSize = false; }
}
protected override void OnPaint(PaintEventArgs e) {
base.OnPaint(e);
int h = this.ClientSize.Height - 2;
Rectangle rc = new Rectangle(new Point(0, 1), new Size(h, h));
ControlPaint.DrawCheckBox(e.Graphics, rc,
this.Checked ? ButtonState.Checked : ButtonState.Normal);
}
}
RadioButton also tried but I don't know how to apply colors and highlight the text.
using System;
using System.Drawing;
using System.Windows.Forms;
namespace WindowsForms
{
public class BiggerCheckBox : CheckBox
{
#region variables
private int _boxsize = 14;
private int _boxlocatx = 0;
private int _boxlocaty = 0;
private int _textX = 16;
private int _textY = 1;
private Color _boxBackColor = Color.Transparent;
private Color _tickColor = Color.Black;
private float _tickSize = 11f;
private Color _boxColor = Color.Black;
private float _tickLeftPosition = 0f;
private float _tickTopPosition = 0f;
#endregion
#region Properties
public int TextLocationX
{
get { return _textX; }
set { _textX = value; Invalidate(); }
}
public int TextLocationY
{
get { return _textY; }
set { _textY = value; Invalidate(); }
}
public int BoxSize
{
get { return _boxsize; }
set { _boxsize = value; Invalidate(); }
}
public int BoxLocationX
{
get { return _boxlocatx; }
set { _boxlocatx = value; Invalidate(); }
}
public int BoxLocationY
{
get { return _boxlocaty; }
set { _boxlocaty = value; Invalidate(); }
}
public Color BoxBackColor
{
get { return _boxBackColor; }
set { _boxBackColor = value; Invalidate(); }
}
public Color TickColor
{
get { return _tickColor; }
set { _tickColor = value; Invalidate(); }
}
public float TickSize
{
get { return _tickSize; }
set { _tickSize = value; Invalidate(); }
}
public Color BoxColor
{
get { return _boxColor; }
set { _boxColor = value; Invalidate(); }
}
public float TickLeftPosition
{
get { return _tickLeftPosition; }
set { _tickLeftPosition = value; Invalidate(); }
}
public float TickTopPosition
{
get { return _tickTopPosition; }
set { _tickTopPosition = value; Invalidate(); }
}
#endregion
#region Constrctors
public BiggerCheckBox()
{
Appearance = Appearance.Button;
FlatStyle = FlatStyle.Flat;
TextAlign = ContentAlignment.MiddleRight;
FlatAppearance.BorderSize = 0;
AutoSize = false;
}
#endregion
#region Methods
protected override void OnPaint(PaintEventArgs pevent)
{
try
{
base.OnPaint(pevent);
pevent.Graphics.Clear(BackColor);
//checkbox text - using draw string method with specified location
using (SolidBrush brushText = new SolidBrush(ForeColor))
{
pevent.Graphics.DrawString(Text, Font, brushText, _textX, _textY);
}
//checkbox box - using rectangle for checkbox box
Rectangle _rectangleBox = new Rectangle(_boxlocatx, _boxlocaty, _boxsize, _boxsize);
//checkbox box - checckbox box back color and border color
using (SolidBrush brushBackColor = new SolidBrush(_boxBackColor))
{
pevent.Graphics.FillRectangle(brushBackColor, _rectangleBox);
}
using (Pen penBoxColor = new Pen(_boxColor))
{
pevent.Graphics.DrawRectangle(penBoxColor, _rectangleBox);
}
//checkbox box - check and uncheck
if (Checked)
{
using (SolidBrush brush = new SolidBrush(_tickColor))
{
using (Font wing = new Font("Wingdings", _tickSize))
{
pevent.Graphics.DrawString("ΓΌ", wing, brush, _tickLeftPosition, _tickTopPosition);
}
}
}
pevent.Dispose();
}
catch (Exception ex)
{
}
}
#endregion
}
}

How can I create a method polymorphism?

I learn programming oriented object, and I want to do this code but I got those problems, I think I don't really know the concept of virtual.
View image 1
Code:
class Joueur
{
private string _nom;
private string _prenom;
private DateTime _dateDeNaissance;
private string _position;
private bool _reserve;
public string nom
{
get { return _nom; }
set { _nom = value; }
}
public string prenom
{
get { return _prenom; }
set { _prenom = value; }
}
public DateTime dateDeNaissance
{
get { return _dateDeNaissance; }
set { _dateDeNaissance = value; }
}
public string position
{
get { return _position; }
set { _position = value; }
}
public bool reserve
{
get { return _reserve; }
set { _reserve = value; }
}
public Joueur()
{
}
public Joueur(string nom, string prenom, DateTime dateDeNaissance, string position, bool reserve)
{
this.nom = nom;
this.prenom = prenom;
this.dateDeNaissance = dateDeNaissance;
this.position = position;
this.reserve = reserve;
}
public double virtual CalculerPrime(int joues, int gagnes)
{
double Prime;
if (reserve == false)
Prime = 10000 * (gagnes / joues);
else
Prime = ((10000 * (gagnes / joues)) / 2);
return Prime;
}
}
You need to do like this in your code:
public virtual double CalculerPrime(int joues, int gagnes)
{
double Prime;
if (reserve == false)
Prime = 10000 * (gagnes / joues);
else
Prime = ((10000 * (gagnes / joues)) / 2);
return Prime;
}

DataAnnotations attribute for float.NaN

I am using DataAnnotations for validation of my ViewModel (WPF) so I can control the enable state of some buttons if the user type in a something that is not a float and if the value is outside of a range.
[Range(0, float.MaxValue, ErrorMessage = "StepSize must be more than 0")]
public float StepSize
{
get { return model.StepSize; }
set
{
model.StepSize = value;
RaisePropertyChangedAndRevalidate(nameof(StepSize));
}
}
private void RaisePropertyChangedAndRevalidate(string propertyName)
{
RaisePropertyChanged(propertyName);
if (_fieldBindingErrors == 0)
{
RaisePropertyChanged(nameof(IsValid));
}
}
private int _fieldBindingErrors = 0;
public ICommand RegisterFieldBindingErrors
{
get
{
return new RelayCommand<ValidationErrorEventArgs>(e =>
{
if (e.Action == ValidationErrorEventAction.Added)
{
_fieldBindingErrors++;
}
else
{
_fieldBindingErrors--;
}
RaisePropertyChanged(nameof(IsValid));
});
}
}
public bool IsValid
{
get
{
bool valid = Validator.TryValidateObject(this,
new ValidationContext(this, null, null),
new List<System.ComponentModel.DataAnnotations.ValidationResult>())
&& _fieldBindingErrors == 0;
return valid;
}
}
Problem is, when I convert the the textbox.Text string to a float I have to set the value to something not valid (should work for general cases also when the Range attribute is not in use). So I set the value to float.NaN.
The problem is that NaN seems to be a valid float, and it even passes the Range validation above.
Is there an attribute I could use to validate that the value is not NaN?
Found a solution, I created a custom validation rule instead and applied it in the XAML.
class StepSizeValidationRule : ValidationRule
{
private int _min;
private int _max;
public StepSizeValidationRule()
{
}
public int Min
{
get { return _min; }
set { _min = value; }
}
public int Max
{
get { return _max; }
set { _max = value; }
}
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
float stepSize = 0;
try
{
if (!float.TryParse(value.ToString(), out stepSize))
{
return new ValidationResult(false, "Not a float");
}
}
catch (Exception e)
{
return new ValidationResult(false, "Not a float " + e.Message);
}
if (float.IsNaN(stepSize))
{
return new ValidationResult(false, "Not a float ");
}
if ((stepSize < Min) || (stepSize > Max))
{
return new ValidationResult(false,
"Please enter a stepSize in the range: " + Min + " - " + Max + ".");
}
else
{
return new ValidationResult(true, null);
}
}
}

How can I check if a class property is set in C#?

I am currently working on a BMI calculator for my C# class. My app asks the user for either their height in feet and inches and their weight in pounds or their height in centimeters and weight in kilograms. Their is a tab control that has buttons for Imperial mode or Metric mode.
If the "calculate" button in the imperial tab is clicked, I need to make sure that the heightFt, heightIn, and weightLbs text boxes have been filled out. Then I convert those to the metric units. If the calculate button in the metric tab is clicked, I need to make sure that the heightCm and weightKg text boxes have been filled out.
Once those are provided, I then convert the height and weight to BMI. If I use if(heightFt == null) I get the following error:
The result of the expression is always 'false' since a value of type 'double' is never equal to 'null' of type 'double?'
How do I fix this?
This is my MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace BMICalculator
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private BMICalc _BMICalc;
public MainWindow()
{
_BMICalc = new BMICalc();
InitializeComponent();
}
private void calculateImperial_Click(object sender, RoutedEventArgs e)
{
_BMICalc.heightFt = Convert.ToDouble(heightFt.Text);
_BMICalc.heightIn = Convert.ToDouble(heightIn.Text);
_BMICalc.weightLbs = Convert.ToDouble(weightLbs.Text);
_BMICalc.doCalculation("Imperial");
if (_BMICalc.error == null)
{
MessageBox.Show("Your BMI is " + _BMICalc.bmi + " and you are " + _BMICalc.category, "Your BMI");
}
}
}
}
This is BMICalc.cs
using System;
using System.Windows;
using System.ComponentModel;
namespace BMICalculator
{
class BMICalc :INotifyPropertyChanged
{
public double _heightFt { get; set; }
public double _heightIn { get; set; }
public double _heightCm { get; set; }
public double _weightLbs { get; set; }
public double _weightKg { get; set; }
public double _bmi { get; set; }
public string _category { get; set; }
public string _error { get; set; }
public double heightFt
{
get { return heightFt; }
set
{
_heightFt = value;
OnPropertyChanged("heightFt");
}
}
public double heightIn
{
get { return _heightIn; }
set
{
_heightIn = value;
OnPropertyChanged("heightIn");
}
}
public double heightCm
{
get { return _heightCm; }
set
{
_heightCm = value;
OnPropertyChanged("heightCm");
}
}
public double weightLbs
{
get { return _weightLbs; }
set
{
_weightLbs = value;
OnPropertyChanged("weightLbs");
}
}
public double weightKg
{
get { return _weightKg; }
set
{
_weightKg = value;
OnPropertyChanged("weightKg");
}
}
public double bmi
{
get { return _bmi; }
set
{
_bmi = value;
OnPropertyChanged("bmi");
}
}
public string error
{
get { return _error; }
set
{
_error = value;
OnPropertyChanged("error");
}
}
public string category
{
get { return _category; }
set
{
_category = value;
OnPropertyChanged("category");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName){
if(PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
public void doCalculation(string calculationMode){
if(calculationMode == "Imperial"){
if (heightFt == null)
{
this.error = "You must provide a value for your height in feet!";
}
else if (heightIn == null)
{
this.error = "You must provide a value for your height in inches!";
}
else if (weightLbs == null)
{
this.error = "You must provide a value for your weight in pounds!";
}
else
{
heightFt = Convert.ToDouble(heightFt);
heightIn = Convert.ToDouble(heightIn);
weightLbs = Convert.ToDouble(weightLbs);
_weightKg = Convert.ToDouble(_weightLbs * (1 / 2.2));
_heightCm = Convert.ToDouble((_heightFt + (_heightIn / 12) / 0.032808));
}
} else if(calculationMode == "Metric"){
this.bmi = weightKg / Math.Pow((heightCm / 100), 2);
if (this.bmi < 18.5)
{
this.category = "underweight";
}
else if (this.bmi >= 18.5 && this.bmi < 24.9)
{
this.category = "normalweight";
}
else if (this.bmi >= 25 && this.bmi <= 29.9)
{
this.category = "overweight";
}
else if (this.bmi > 30)
{
this.category = "obese";
}
}
}
}
}
}
You can make you double properties to be nullable so you can compare to null (the default).
Example:
public double? heightIn
{
get { return _heightIn; }
set {
_heightIn = value;
OnPropertyChanged("heightIn");
}
}
In this case, make sure you change the type of the corresponding private variables to match.
You never set a default value for your properties. As double cannot be null you'll probably want to check against 0 instead. The properties you begin with underscores should just be private variables with default values. Also consider using metric only internally.
class BMICalc :INotifyPropertyChanged
{
private double _heightFt = 0;
private double _heightIn = 0;
private double _heightCm = 0;
private double _weightLbs = 0;
private double _weightKg = 0;
private double _bmi = 0;
private string _category = null;
private string _error = null;
public double heightFt
{
get { return _heightFt; }
set
{
_heightFt = value;
OnPropertyChanged("heightFt");
}
}
public double heightIn
{
get { return _heightIn; }
set
{
_heightIn = value;
OnPropertyChanged("heightIn");
}
}
public double heightCm
{
get { return _heightCm; }
set
{
_heightCm = value;
OnPropertyChanged("heightCm");
}
}
public double weightLbs
{
get { return _weightLbs; }
set
{
_weightLbs = value;
OnPropertyChanged("weightLbs");
}
}
public double weightKg
{
get { return _weightKg; }
set
{
_weightKg = value;
OnPropertyChanged("weightKg");
}
}
public double bmi
{
get { return _bmi; }
set
{
_bmi = value;
OnPropertyChanged("bmi");
}
}
public string error
{
get { return _error; }
set
{
_error = value;
OnPropertyChanged("error");
}
}
public string category
{
get { return _category; }
set
{
_category = value;
OnPropertyChanged("category");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName){
if(PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
public void doCalculation(string calculationMode){
if(calculationMode == "Imperial"){
if (heightFt == null)
{
this.error = "You must provide a value for your height in feet!";
}
else if (heightIn == null)
{
this.error = "You must provide a value for your height in inches!";
}
else if (weightLbs == null)
{
this.error = "You must provide a value for your weight in pounds!";
}
else
{
heightFt = Convert.ToDouble(heightFt);
heightIn = Convert.ToDouble(heightIn);
weightLbs = Convert.ToDouble(weightLbs);
_weightKg = Convert.ToDouble(_weightLbs * (1 / 2.2));
_heightCm = Convert.ToDouble((_heightFt + (_heightIn / 12) / 0.032808));
}
} else if(calculationMode == "Metric"){
this.bmi = weightKg / Math.Pow((heightCm / 100), 2);
if (this.bmi < 18.5)
{
this.category = "underweight";
}
else if (this.bmi >= 18.5 && this.bmi < 24.9)
{
this.category = "normalweight";
}
else if (this.bmi >= 25 && this.bmi <= 29.9)
{
this.category = "overweight";
}
else if (this.bmi > 30)
{
this.category = "obese";
}
}
}
}
}

Categories

Resources