I was wondering if anyone could show me a simple way of creating buttons in XNA.
Preferably a way to add a function when its clicked, and a way to add and remove them easily.
I recommend using the NeoForce Controls Library for GUI related problems - it has buttons, among the other useful GUI controls including popup windows, list views, combo boxes, and so on.
If you are writing a button class for the learning experience... well, try learning more about it yourself via Google before asking for help.
ADDENDUM
This is some code that I've written for buttons. Maybe it can serve as a starting point. I use it in my 2D game engine, so it has been debugged and tested.
/// <summary>
/// A control that changes appearance when it is hovered over and triggers some effect when it is clicked
/// </summary>
public class EnigmaButton
{
/// <summary>
/// The method signature for notification when a button is clicked
/// </summary>
/// <param name="sender">EnigmaButton that was clicked</param>
public delegate void OnClickEvent(EnigmaButton sender);
/// <summary>
/// Types of textures used for Enigma Buttons
/// </summary>
public enum TextureType { Normal, Over, Press }
#region Variables
protected IVisualExposer m_ui;
protected Rectangle m_bounds;
IInputExposer m_input;
bool m_over = false, m_press = false, m_wasPressed = false;
Dictionary<TextureType, EnigmaResource<Texture2D>> m_textures;
string m_text, m_name;
EnigmaResource<SpriteFont> m_font;
int m_minTextShadow, m_maxTextShadow;
Color m_textTint;
public event OnClickEvent OnClick;
#endregion
/// <summary>
/// A control that changes appearance when it is hovered over and triggers some effect when it is clicked
/// </summary>
/// <param name="ui">Graphical assets</param>
/// <param name="input">Input exposer for mouse input and XBox controller input</param>
/// <param name="reader">XMLReader for the definition of the controller</param>
/// <param name="pos">Bounds of the controller</param>
public EnigmaButton(IVisualExposer ui, IInputExposer input, XmlReader reader, Rectangle pos)
{
m_ui = ui;
m_bounds = pos;
m_textures = new Dictionary<TextureType, EnigmaResource<Texture2D>>();
m_input = input;
Enabled = true;
#region Reading
string name;
bool started = false, insideText = false;
while (reader.Read())
{
if (reader.MoveToContent() == XmlNodeType.Element)
{
name = reader.Name.ToLower();
if (name == "button")
{
if (started)
throw new Exception("Already started.");
started = true;
m_name = reader.GetAttribute("name") ?? string.Empty;
}
else if (!started)
throw new Exception("Not started");
else if (name == "text")
{
m_font = new EnigmaResource<SpriteFont>();
m_font.Filepath = reader.GetAttribute("font");
string minShadow = reader.GetAttribute("minShadow"), maxShadow = reader.GetAttribute("maxShadow");
m_minTextShadow = minShadow != null ? int.Parse(minShadow) : 0;
m_maxTextShadow = maxShadow != null ? int.Parse(maxShadow) : 2;
m_text = reader.GetAttribute("text") ?? string.Empty;
insideText = true;
m_textTint = Color.White;
}
else if (name == "bounds")
{
insideText = false;
m_bounds = new Rectangle(int.Parse(reader.GetAttribute("x")), int.Parse(reader.GetAttribute("y")),
int.Parse(reader.GetAttribute("width")), int.Parse(reader.GetAttribute("height")));
}
else if (name == "texture")
{
insideText = false;
TextureType texType = (TextureType)Enum.Parse(typeof(TextureType), reader.GetAttribute("type"));
if (m_textures.ContainsKey(texType))
throw new Exception("A texture of type '" + texType.ToString() + "' cannot be registered twice");
EnigmaResource<Texture2D> res = new EnigmaResource<Texture2D>();
res.Filepath = reader.ReadString();
m_textures.Add(texType, res);
}
else if (name == "tint")
{
if (!insideText)
throw new Exception("Tints can only be for text");
float a, r, g, b;
string[] split = reader.ReadString().Split(',');
if (split.Length != 4)
throw new Exception("Colors must be RGBA");
r = float.Parse(split[0].Trim());
g = float.Parse(split[1].Trim());
b = float.Parse(split[2].Trim());
a = float.Parse(split[3].Trim());
m_textTint = new Color(r, g, b, a);
}
}
}
#endregion
if (!m_textures.ContainsKey(TextureType.Normal))
throw new Exception("A button must have at least a '" + TextureType.Normal.ToString() + "' texture");
}
#region Methods
public void Initialize()
{
}
public void LoadContent()
{
EnigmaResource<Texture2D> res;
for (int i = 0; i < m_textures.Count; i++)
{
res = m_textures[m_textures.ElementAt(i).Key];
res.Resource = m_ui.Content.Load<Texture2D>(res.Filepath);
m_textures[m_textures.ElementAt(i).Key] = res;
}
if (m_font.Filepath != null)
m_font.Resource = m_ui.Content.Load<SpriteFont>(m_font.Filepath);
}
public void Update(GameTime gameTime)
{
m_wasPressed = m_press;
m_over = m_bounds.Contains(m_input.MouseX, m_input.MouseY);
m_press = m_over ? m_wasPressed ? m_input.IsMouseLeftPressed || m_input.IsButtonPressed(Buttons.A) : m_input.IsMouseLeftTriggered || m_input.IsButtonTriggered(Buttons.A) : false;
if (!m_wasPressed && m_press && OnClick != null)
OnClick(this);
}
public void Draw(GameTime gameTime)
{
Texture2D toDraw = m_textures[TextureType.Normal].Resource;
if (Enabled)
{
if (m_press && m_textures.ContainsKey(TextureType.Press))
toDraw = m_textures[TextureType.Press].Resource;
else if (m_over && m_textures.ContainsKey(TextureType.Over))
toDraw = m_textures[TextureType.Over].Resource;
}
m_ui.SpriteBatch.Draw(toDraw, m_bounds, Enabled ? Color.White : Color.Gray);
if (m_font.Resource != null)
{
Vector2 pos = new Vector2(m_bounds.X, m_bounds.Y);
Vector2 size = m_font.Resource.MeasureString(m_text);
pos.X += (m_bounds.Width - size.X) / 2;
pos.Y += (m_bounds.Height - size.Y) / 2;
UIHelper.DrawShadowedString(m_ui, m_font.Resource, m_text, pos, m_textTint, m_minTextShadow, m_maxTextShadow);
}
}
#endregion
#region Properties
/// <summary>
/// Gets or sets the name of the button
/// </summary>
public string Name
{
get { return m_name; }
set { m_name = value ?? m_name; }
}
/// <summary>
/// Gets or sets the text drawn in the button.
/// WARNING: Will overflow if the text does not normally fit.
/// </summary>
public string Text
{
get { return m_text; }
set { m_text = value ?? string.Empty; }
}
/// <summary>
/// Gets or sets the bounds of the button
/// </summary>
public Rectangle Bounds
{
get { return m_bounds; }
set { m_bounds = value; }
}
/// <summary>
/// Whether or not the control is enabled
/// </summary>
public bool Enabled { get; set; }
#endregion
}
Related
I am inheriting from Xamarin..Android.SliderRenderer to create a circular slider. I created a View class and assembled them already:
[assembly: ExportRendererAttribute(typeof(CircleSliderView), typeof(CircleSliderViewRenderer))]
public class CircleSliderViewRenderer : SliderRenderer
I carefully avoid the SetWillNotDraw trap in constructor:
this.SetWillNotDraw(false);
Finally, override the OnDraw method to draw something else than the original one:
protected override void OnDraw(Canvas canvas)
{
...
DrawTrack(canvas, view.MaximumTrackColor.ToAndroid(), maxSweep);
DrawTrack(canvas, view.MinimumTrackColor.ToAndroid(), minSweep);
// no call to super.OnDraw()
}
As a result, I have an arc drawn:
However, I have 2 issues here:
Old slider drawing is still there.
My OnDraw is called once and never again (even after value change).
Apparently, there is another method than OnDraw that is being called continually (susceptibly when the value changes). But the API docs do not help at all on finding this method. Does anyone know which methods I should override to solve above issues?
Thank you in advance.
You could custom a circle slider which Inherited the View,then use ViewRenderer instead of SliderRenderer.
Custom CircularSlider in Android Project:
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using Android.Content;
using Android.Graphics;
using Android.Util;
using Android.Views;
using Java.Lang;
using Math = Java.Lang.Math;
namespace EntryCa.Droid
{
public class CircularSlider : View, INotifyPropertyChanged
{
int _arcRadius;
float _progressSweep;
RectF _arcRect = new RectF();
Paint _arcPaint;
Paint _progressPaint;
int _translateX;
int _translateY;
int _thumbXPos;
int _thumbYPos;
float _touchInsideIgnoreRadius;
float _touchOutsideIgnoreRadius;
int _touchCorrection = 40;
/// <summary>
/// This indicates how many points a touch event can go inside or outside the circle before the slider stops updating.
/// This may never exceed half of the controls size (this can create unwanted behaviour).
/// The value must be greater or equal to 0.
/// </summary>
public int TouchCorrection
{
get
{
return _touchCorrection;
}
set
{
if (_touchCorrection < 0)
throw new ArgumentOutOfRangeException(nameof(TouchCorrection), "The value must be at least 0");
_touchCorrection = value;
OnPropertyChanged();
}
}
int _sweepAngle = 180;
/// <summary>
/// This indicates how many degrees the circle is used.
/// The value must be between 0 and 360
/// </summary>
public int SweepAngle
{
get { return _sweepAngle; }
set
{
if (value < 0 || value > 360)
throw new ArgumentOutOfRangeException(nameof(SweepAngle), "The value must be between 0 and 360");
_sweepAngle = value;
if (Width > 0 && Height > 0)
{
CalculateArcRect(Width, Height);
UpdateProgress();
}
Invalidate();
OnPropertyChanged();
}
}
int _startAngle = 180;
/// <summary>
/// This indicates at how many degrees in the circle the indicator will start.
/// The value must be between 0 and 360.
/// </summary>
public int StartAngle
{
get { return _startAngle; }
set
{
if (value < 0 || value > 360)
throw new ArgumentOutOfRangeException(nameof(StartAngle), "The value must be between 0 and 360");
_startAngle = value;
if (Width > 0 && Height > 0)
{
CalculateArcRect(Width, Height);
UpdateProgress();
}
Invalidate();
OnPropertyChanged();
}
}
/// <summary>
/// The color of the uncompleted progress indicator.
/// </summary>
public Color Color
{
get
{
return _arcPaint.Color;
}
set
{
_arcPaint.Color = value;
Invalidate();
OnPropertyChanged();
}
}
/// <summary>
/// The color of the completed progress indicator.
/// </summary>
public Color ProgressColor
{
get
{
return _progressPaint.Color;
}
set
{
_progressPaint.Color = value;
Invalidate();
OnPropertyChanged();
}
}
Bitmap _thumb;
/// <summary>
/// The thumb image to indicate the current progress.
/// The bitmap must have the same width and height.
/// </summary>
public Bitmap Thumb
{
get
{
return _thumb;
}
set
{
if (value != null && value.Width != value.Height)
throw new ArgumentException("The image must be a square (same width and height)", nameof(Thumb));
_thumb = value;
if (Width > 0 && Height > 0)
{
CalculateArcRect(Width, Height);
UpdateProgress();
}
OnPropertyChanged();
}
}
/// <summary>
/// The line width in pixels of the circle.
/// </summary>
public int LineWidth
{
get
{
return (int)_arcPaint.StrokeWidth;
}
set
{
_arcPaint.StrokeWidth = value;
_progressPaint.StrokeWidth = value;
if (Width > 0 && Height > 0)
{
CalculateArcRect(Width, Height);
UpdateThumbPosition();
}
Invalidate();
OnPropertyChanged();
}
}
/// <summary>
/// This indicates if the circle line has rounded corners at the end of the line.
/// </summary>
public bool RoundEdges
{
get
{
return _arcPaint.StrokeCap == Paint.Cap.Round;
}
set
{
_arcPaint.StrokeCap = value ? Paint.Cap.Round : Paint.Cap.Square;
_progressPaint.StrokeCap = value ? Paint.Cap.Round : Paint.Cap.Square;
Invalidate();
OnPropertyChanged();
}
}
int _maximum;
/// <summary>
/// The maximum value of the progress.
/// </summary>
public int Maximum
{
get
{
return _maximum;
}
set
{
if (value < 0)
throw new IllegalStateException("Maximum can not be less than 0");
if (value < Progress)
throw new IllegalStateException("Maximum can not be less than Progress value" + Progress);
if (value != _maximum)
{
_maximum = value;
UpdateProgress();
OnPropertyChanged();
}
}
}
int _progress;
/// <summary>
/// The current progress.
/// </summary>
public int Progress
{
get
{
return _progress;
}
set
{
if (value < 0)
throw new IllegalStateException("Progress can not be less than 0");
if (value > Maximum)
throw new IllegalStateException("Progress can not be more than Maximum value " + Maximum);
if (value != _progress)
{
_progress = value;
UpdateProgress();
ProgressChanged?.Invoke(this, value);
OnPropertyChanged();
}
}
}
bool _clockwise = true;
/// <summary>
/// This indicates if the slider should work clockwise or counter clockwise.
/// </summary>
public bool Clockwise
{
get
{
return _clockwise;
}
set
{
_clockwise = value;
Invalidate();
OnPropertyChanged();
}
}
/// <summary>
/// This indicates if the user can interact with the control or not
/// </summary>
public override bool Enabled
{
get
{
return base.Enabled;
}
set
{
base.Enabled = value;
OnPropertyChanged();
}
}
/// <summary>
/// Triggered when one of the custom properties is changed.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Triggered when the progress value has changed.
/// </summary>
public event EventHandler<int> ProgressChanged;
public CircularSlider(Context context)
: base(context)
{
Init();
}
public CircularSlider(Context context, IAttributeSet attrs)
: base(context, attrs)
{
Init();
}
public CircularSlider(Context context, IAttributeSet attrs, int defStyle)
: base(context, attrs, defStyle)
{
Init();
}
void Init()
{
_arcPaint = new Paint
{
AntiAlias = true,
StrokeCap = Paint.Cap.Round
};
_arcPaint.SetStyle(Paint.Style.Stroke);
_progressPaint = new Paint
{
AntiAlias = true,
StrokeCap = Paint.Cap.Round
};
_progressPaint.SetStyle(Paint.Style.Stroke);
LineWidth = (int)(4 * Context.Resources.DisplayMetrics.Density);
UpdateProgress();
}
protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
base.OnMeasure(widthMeasureSpec, heightMeasureSpec);
var width = GetDefaultSize(SuggestedMinimumWidth, widthMeasureSpec);
var height = GetDefaultSize(SuggestedMinimumHeight, heightMeasureSpec);
CalculateArcRect(width, height);
UpdateThumbPosition();
// Don't use the exact radius but include TouchCorrection or else this makes interaction too tricky
if (Thumb != null)
{
_touchInsideIgnoreRadius = _arcRadius - (Math.Min(Thumb.Width, Thumb.Height) + TouchCorrection);
_touchOutsideIgnoreRadius = _arcRadius + (Math.Min(Thumb.Width, Thumb.Height) + TouchCorrection);
}
else
{
_touchInsideIgnoreRadius = _arcRadius - TouchCorrection;
_touchOutsideIgnoreRadius = _arcRadius + TouchCorrection;
}
}
protected override void OnDraw(Canvas canvas)
{
base.OnDraw(canvas);
if (!Clockwise)
canvas.Scale(-1, 1, _arcRect.CenterX(), _arcRect.CenterY());
canvas.DrawArc(_arcRect, StartAngle, SweepAngle, false, _arcPaint);
canvas.DrawArc(_arcRect, StartAngle, _progressSweep, false, _progressPaint);
if (Thumb != null)
{
var left = (_translateX - _thumbXPos) - (Thumb.Width / 2);
var top = (_translateY - _thumbYPos) - (Thumb.Height / 2);
canvas.DrawBitmap(Thumb, left, top, null);
}
}
void CalculateArcRect(int width, int height)
{
_translateX = (int)(width * 0.5f);
_translateY = (int)(height * 0.5f);
var min = Math.Min(width, height);
if (Thumb != null)
{
var arcDiameter = min - (LineWidth + Thumb.Width);
_arcRadius = arcDiameter / 2;
var top = height / 2 - (arcDiameter / 2);
var left = width / 2 - (arcDiameter / 2);
_arcRect.Set(left, top, left + arcDiameter, top + arcDiameter);
}
else
{
var arcDiameter = min - LineWidth;
_arcRadius = arcDiameter / 2;
var top = height / 2 - (arcDiameter / 2);
var left = width / 2 - (arcDiameter / 2);
_arcRect.Set(left, top, left + arcDiameter, top + arcDiameter);
}
}
public override bool OnTouchEvent(MotionEvent e)
{
if (Enabled)
{
Parent?.RequestDisallowInterceptTouchEvent(true);
switch (e.Action)
{
case MotionEventActions.Down:
case MotionEventActions.Move:
UpdateOnTouch(e);
break;
case MotionEventActions.Up:
case MotionEventActions.Cancel:
Pressed = false;
Parent?.RequestDisallowInterceptTouchEvent(true);
break;
}
return true;
}
return false;
}
void UpdateOnTouch(MotionEvent e)
{
if (IgnoreTouch(e.GetX(), e.GetY()))
return;
Pressed = true;
var touchAngle = GetTouchDegrees(e.GetX(), e.GetY());
var progress = GetProgressForAngle(touchAngle);
if (progress >= 0)
{
Progress = progress;
}
}
bool IgnoreTouch(float xPos, float yPos)
{
var x = xPos - _translateX;
var y = yPos - _translateY;
return PointIsInsideCircle(_touchInsideIgnoreRadius, x, y) || !PointIsInsideCircle(_touchOutsideIgnoreRadius, x, y);
}
bool PointIsInsideCircle(double circleRadius, double x, double y)
{
return (Math.Pow(x, 2) + Math.Pow(y, 2)) < (Math.Pow(circleRadius, 2));
}
double GetTouchDegrees(float xPos, float yPos)
{
float x = xPos - _translateX;
float y = yPos - _translateY;
if (!Clockwise)
x = -x;
// Convert to arc Angle
var angle = Math.ToDegrees(Math.Atan2(y, x) + (Math.Pi / 2));
angle -= 90;
if (angle < 0)
{
angle = 360 + angle;
}
angle -= StartAngle;
return angle;
}
int GetProgressForAngle(double angle)
{
var valuePerDegree = (float)Maximum / SweepAngle;
var progress = (int)Math.Round(valuePerDegree * angle);
if (progress < 0 || progress > Maximum)
return -1;
return progress;
}
void UpdateProgress()
{
_progressSweep = (float)Progress / Maximum * SweepAngle;
UpdateThumbPosition();
Invalidate();
}
void UpdateThumbPosition()
{
var thumbAngle = StartAngle + _progressSweep + 180;
_thumbXPos = (int)(_arcRadius * Math.Cos(Math.ToRadians(thumbAngle)));
_thumbYPos = (int)(_arcRadius * Math.Sin(Math.ToRadians(thumbAngle)));
}
/// <summary>
/// Sets the thumb resource identifier.
/// This will automatically be converted to a bitmap and set to the Thumb property.
/// </summary>
public void SetThumbResourceId(int resId)
{
Thumb = BitmapFactory.DecodeResource(Resources, resId);
}
public void OnPropertyChanged([CallerMemberName]string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
the in your CircleSliderViewRenderer :
class CircleSliderViewRenderer: ViewRenderer
{
Context mContext;
CircularSlider _slider;
public CircleSliderViewRenderer(Context context) : base(context)
{
mContext = context;
}
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.View> e)
{
base.OnElementChanged(e);
_slider = new CircularSlider(mContext);
_slider.Color = Android.Graphics.Color.Red;
_slider.ProgressColor = Android.Graphics.Color.Yellow;
_slider.Maximum = 50;
_slider.Progress = 20;
_slider.ProgressChanged += _slider_ProgressChanged;
SetNativeControl(_slider);
}
private void _slider_ProgressChanged(object sender, int e)
{
//when the progress change,you could do something here
}
}
the effect like this:
I have an issue with an textbox, once it was to accept just 3 values know i have update it to nvarchar(MAX) I updated the EntityModelDB but still after this i'm receivein an error when i add more than 3 values in my textbox
Here is my code
if (!Regex.Match(item.treatments_code, #"^[A-Z0-9\-]{6}$").Success)
{
ret = false;
errors = errors.Concat(new string[] { language.text003 }).ToArray();
}
Here is my error
An exception of type 'System.ArgumentException' occurred in DGUIGHF.dll but was not handled in user code
Additional information: Invalid code format. 3 character, uppercase letters [A-Z] or numbers [0-9], or minus '-'.
FormTreatments.cs
using DG.Data.Model.Helpers;
using DG.DentneD.Forms.Objects;
using DG.DentneD.Helpers;
using DG.DentneD.Model;
using DG.DentneD.Model.Entity;
using DG.UI.GHF;
using SMcMaster;
using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.Windows.Forms;
using Zuby.ADGV;
namespace DG.DentneD.Forms
{
public partial class FormTreatments : DGUIGHFForm
{
private DentneDModel _dentnedModel = null;
private TabElement tabElement_tabTreatments = new TabElement();
private TabElement tabElement_tabTreatmentsPrices = new TabElement();
private readonly BoxLoader _boxLoader = null;
/// <summary>
/// Constructor
/// </summary>
public FormTreatments()
{
InitializeComponent();
(new TabOrderManager(this)).SetTabOrder(TabOrderManager.TabScheme.AcrossFirst);
Initialize(Program.uighfApplication);
_dentnedModel = new DentneDModel();
_dentnedModel.LanguageHelper.LoadFromFile(Program.uighfApplication.LanguageFilename);
_boxLoader = new BoxLoader(_dentnedModel);
}
/// <summary>
/// Add components language
/// </summary>
public override void AddLanguageComponents()
{
//main
LanguageHelper.AddComponent(this);
LanguageHelper.AddComponent(treatmentsidDataGridViewTextBoxColumn, this.GetType().Name, "HeaderText");
LanguageHelper.AddComponent(nameDataGridViewTextBoxColumn, this.GetType().Name, "HeaderText");
LanguageHelper.AddComponent(codeDataGridViewTextBoxColumn, this.GetType().Name, "HeaderText");
LanguageHelper.AddComponent(typeDataGridViewTextBoxColumn, this.GetType().Name, "HeaderText");
LanguageHelper.AddComponent(button_export);
//tabTreatments
LanguageHelper.AddComponent(tabPage_tabTreatments);
LanguageHelper.AddComponent(button_tabTreatments_new);
LanguageHelper.AddComponent(button_tabTreatments_edit);
LanguageHelper.AddComponent(button_tabTreatments_delete);
LanguageHelper.AddComponent(button_tabTreatments_save);
LanguageHelper.AddComponent(button_tabTreatments_cancel);
LanguageHelper.AddComponent(treatments_idLabel);
LanguageHelper.AddComponent(treatments_nameLabel);
LanguageHelper.AddComponent(treatments_codeLabel);
LanguageHelper.AddComponent(treatmentstypes_idLabel);
LanguageHelper.AddComponent(treatments_mexpirationLabel);
LanguageHelper.AddComponent(treatments_mexpirationinfoLabel);
LanguageHelper.AddComponent(treatments_priceLabel);
LanguageHelper.AddComponent(treatments_notesLabel);
LanguageHelper.AddComponent(taxes_idLabel);
LanguageHelper.AddComponent(treatments_isunitpriceCheckBox);
LanguageHelper.AddComponent(button_tabTreatments_unsettaxesid);
//tabTreatmentsPrices
LanguageHelper.AddComponent(tabPage_tabTreatmentsPrices);
LanguageHelper.AddComponent(label_tabTreatmentsPrices_filterpriceslists);
LanguageHelper.AddComponent(treatmentspricesidDataGridViewTextBoxColumn, this.GetType().Name, "HeaderText");
LanguageHelper.AddComponent(pricelistDataGridViewTextBoxColumn, this.GetType().Name, "HeaderText");
LanguageHelper.AddComponent(priceDataGridViewTextBoxColumn, this.GetType().Name, "HeaderText");
LanguageHelper.AddComponent(button_tabTreatmentsPrices_new);
LanguageHelper.AddComponent(button_tabTreatmentsPrices_edit);
LanguageHelper.AddComponent(button_tabTreatmentsPrices_delete);
LanguageHelper.AddComponent(button_tabTreatmentsPrices_save);
LanguageHelper.AddComponent(button_tabTreatmentsPrices_cancel);
LanguageHelper.AddComponent(treatmentsprices_idLabel);
LanguageHelper.AddComponent(treatmentspriceslists_idLabel);
LanguageHelper.AddComponent(treatmentsprices_priceLabel);
}
/// <summary>
/// Form language dictionary
/// </summary>
public class FormLanguage : IDGUIGHFLanguage
{
public string exportColumnCode = "Code";
public string exportColumnType = "Type";
public string exportColumnName = "Name";
public string exportColumnPrice = "Price";
public string exportSaveFileDialogTitle = "Save an Excel File";
public string exportErrorMessage = "Error writing file '{0}'.";
public string exportErrorTitle = "Error";
public string exportSuccessMessage = "File created. Do you want to open it with your default application?";
public string exportSuccessTitle = "Open";
}
/// <summary>
/// Form language
/// </summary>
public FormLanguage language = new FormLanguage();
/// <summary>
/// Initialize TabElements
/// </summary>
protected override void InitializeTabElements()
{
//set Readonly OnSetEditingMode for Controls
DisableReadonlyCheckOnSetEditingModeControlCollection.Add(typeof(DataGridView));
DisableReadonlyCheckOnSetEditingModeControlCollection.Add(typeof(AdvancedDataGridView));
//set Main BindingSource
BindingSourceMain = vTreatmentsBindingSource;
GetDataSourceMain = GetDataSource_main;
//set Main TabControl
TabControlMain = tabControl_main;
//set Main Panels
PanelFiltersMain = panel_filters;
PanelListMain = panel_list;
PanelsExtraMain = null;
//set tabTreatments
tabElement_tabTreatments = new TabElement()
{
TabPageElement = tabPage_tabTreatments,
ElementItem = new TabElement.TabElementItem()
{
PanelData = panel_tabTreatments_data,
PanelActions = panel_tabTreatments_actions,
PanelUpdates = panel_tabTreatments_updates,
ParentBindingSourceList = vTreatmentsBindingSource,
GetParentDataSourceList = GetDataSource_main,
BindingSourceEdit = treatmentsBindingSource,
GetDataSourceEdit = GetDataSourceEdit_tabTreatments,
AfterSaveAction = AfterSaveAction_tabTreatments,
AddButton = button_tabTreatments_new,
UpdateButton = button_tabTreatments_edit,
RemoveButton = button_tabTreatments_delete,
SaveButton = button_tabTreatments_save,
CancelButton = button_tabTreatments_cancel,
Add = Add_tabTreatments,
Update = Update_tabTreatments,
Remove = Remove_tabTreatments
}
};
//set tabTreatmentsPrices
tabElement_tabTreatmentsPrices = new TabElement()
{
TabPageElement = tabPage_tabTreatmentsPrices,
ElementListItem = new TabElement.TabElementListItem()
{
PanelFilters = panel_tabTreatmentsPrices_filters,
PanelList = panel_tabTreatmentsPrices_list,
PanelData = panel_tabTreatmentsPrices_data,
PanelActions = panel_tabTreatmentsPrices_actions,
PanelUpdates = panel_tabTreatmentsPrices_updates,
BindingSourceList = vTreatmentsPricesBindingSource,
GetDataSourceList = GetDataSourceList_tabTreatmentsPrices,
BindingSourceEdit = treatmentspricesBindingSource,
GetDataSourceEdit = GetDataSourceEdit_tabTreatmentsPrices,
AfterSaveAction = AfterSaveAction_tabTreatmentsPrices,
AddButton = button_tabTreatmentsPrices_new,
IsAddButtonDefaultClickEventAttached = false,
UpdateButton = button_tabTreatmentsPrices_edit,
RemoveButton = button_tabTreatmentsPrices_delete,
SaveButton = button_tabTreatmentsPrices_save,
CancelButton = button_tabTreatmentsPrices_cancel,
Add = Add_tabTreatmentsPrices,
Update = Update_tabTreatmentsPrices,
Remove = Remove_tabTreatmentsPrices
}
};
//set Elements
TabElements.Add(tabElement_tabTreatments);
TabElements.Add(tabElement_tabTreatmentsPrices);
}
/// <summary>
/// Loader
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void FormTreatments_Load(object sender, EventArgs e)
{
IsBindingSourceLoading = true;
advancedDataGridView_main.SortASC(advancedDataGridView_main.Columns[2]);
advancedDataGridView_main.SortASC(advancedDataGridView_main.Columns[1]);
advancedDataGridView_main.SortASC(advancedDataGridView_main.Columns[3]);
IsBindingSourceLoading = false;
PreloadView();
ReloadView();
}
/// <summary>
/// Preload View
/// </summary>
private void PreloadView()
{
IsBindingSourceLoading = true;
_boxLoader.LoadComboBoxTreatmentsTypes(treatmentstypes_idComboBox);
_boxLoader.LoadComboBoxTreatmentsPricesLists(treatmentspriceslists_idComboBox);
_boxLoader.LoadComboBoxTaxes(taxes_idComboBox);
_boxLoader.LoadComboBoxFilterTreatmentsPricesLists(comboBox_tabTreatmentsPrices_filterPriceslists);
IsBindingSourceLoading = false;
}
/// <summary>
/// Reset all the tab datagrid
/// </summary>
private void ResetTabsDataGrid()
{
IsBindingSourceLoading = true;
advancedDataGridView_tabTreatmentsPrices_list.CleanFilterAndSort();
advancedDataGridView_tabTreatmentsPrices_list.SortASC(advancedDataGridView_tabTreatmentsPrices_list.Columns[1]);
IsBindingSourceLoading = false;
}
/// <summary>
/// Get main list DataSource
/// </summary>
/// <returns></returns>
private object GetDataSource_main()
{
ResetTabsDataGrid();
IEnumerable<VTreatments> vTreatments =
_dentnedModel.Treatments.List().Select(
r => new VTreatments
{
treatments_id = r.treatments_id,
code = r.treatments_code,
type = _dentnedModel.TreatmentsTypes.Find(r.treatmentstypes_id).treatmentstypes_name,
name = r.treatments_name
}).ToList();
return DGDataTableUtils.ToDataTable<VTreatments>(vTreatments);
}
/// <summary>
/// Main list current element changed hanlder
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void vTreatmentsBindingSource_CurrentChanged(object sender, EventArgs e)
{
if (IsBindingSourceLoading)
return;
//get current itme
int treatments_id = -1;
if (vTreatmentsBindingSource.Current != null)
{
treatments_id = (((DataRowView)vTreatmentsBindingSource.Current).Row).Field<int>("treatments_id");
}
//set treatments fields
treatments_mexpirationTextBox.Text = "";
if (treatments_id != -1)
{
treatments treatment = _dentnedModel.Treatments.Find(treatments_id);
treatments_mexpirationTextBox.Text = treatment.treatments_mexpiration.ToString();
}
//reset treatments prices filter
comboBox_tabTreatmentsPrices_filterPriceslists.SelectedIndex = -1;
}
/// <summary>
/// Export click
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button_export_Click(object sender, EventArgs e)
{
string filename = null;
SaveFileDialog saveFileDialog = new SaveFileDialog();
saveFileDialog.Filter = "Excel|*.xls";
saveFileDialog.Title = language.exportSaveFileDialogTitle; ;
saveFileDialog.ShowDialog();
filename = saveFileDialog.FileName;
if (!String.IsNullOrEmpty(filename))
{
Cursor.Current = Cursors.WaitCursor;
DataTable datatable = new DataTable();
datatable.Clear();
datatable.Columns.Add(language.exportColumnCode);
datatable.Columns.Add(language.exportColumnType);
datatable.Columns.Add(language.exportColumnName);
datatable.Columns.Add(language.exportColumnPrice);
foreach (treatmentspriceslists treatmentspriceslist in _dentnedModel.TreatmentsPricesLists.List().OrderBy(r => r.treatmentspriceslists_name))
{
datatable.Columns.Add(language.exportColumnPrice + "-" + treatmentspriceslist.treatmentspriceslists_id);
}
//add datatable columns
foreach (treatments treatment in _dentnedModel.Treatments.List().OrderBy(r => r.treatments_code))
{
DataRow row = datatable.NewRow();
row[language.exportColumnCode] = treatment.treatments_code;
row[language.exportColumnType] = _dentnedModel.TreatmentsTypes.Find(treatment.treatmentstypes_id).treatmentstypes_name;
row[language.exportColumnName] = treatment.treatments_name;
row[language.exportColumnPrice] = treatment.treatments_price;
foreach (treatmentspriceslists treatmentspriceslist in _dentnedModel.TreatmentsPricesLists.List().OrderBy(r => r.treatmentspriceslists_name))
{
Nullable<decimal> price = null;
treatmentsprices treatmentsprice = _dentnedModel.TreatmentsPrices.FirstOrDefault(r => r.treatments_id == treatment.treatments_id && r.treatmentspriceslists_id == treatmentspriceslist.treatmentspriceslists_id);
if (treatmentsprice != null)
{
price = treatmentsprice.treatmentsprices_price;
}
row[language.exportColumnPrice + "-" + treatmentspriceslist.treatmentspriceslists_id] = price;
}
datatable.Rows.Add(row);
}
Cursor.Current = Cursors.Default;
//export to excel
DataSet dataset = new DataSet();
dataset.Tables.Add(datatable);
if (!String.IsNullOrEmpty(filename))
{
try
{
ExcelExporter.CreateWorkbook(filename, dataset);
}
catch
{
MessageBox.Show(String.Format(language.exportErrorMessage, filename), language.exportErrorTitle, MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
if (MessageBox.Show(language.exportSuccessMessage, language.exportSuccessTitle, MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.Yes)
{
try
{
Process.Start(filename);
}
catch { }
}
}
}
}
#region tabTreatments
/// <summary>
/// Load the tab DataSource
/// </summary>
/// <returns></returns>
private object GetDataSourceEdit_tabTreatments()
{
return DGUIGHFData.LoadEntityFromCurrentBindingSource<treatments, DentneDModel>(_dentnedModel.Treatments, vTreatmentsBindingSource, new string[] { "treatments_id" });
}
/// <summary>
/// Do actions after Save
/// </summary>
/// <param name="item"></param>
private void AfterSaveAction_tabTreatments(object item)
{
DGUIGHFData.SetBindingSourcePosition<treatments, DentneDModel>(_dentnedModel.Treatments, item, vTreatmentsBindingSource);
}
/// <summary>
/// Add an item
/// </summary>
/// <param name="item"></param>
private void Add_tabTreatments(object item)
{
DGUIGHFData.Add<treatments, DentneDModel>(_dentnedModel.Treatments, item);
//update mexpiration
if (!String.IsNullOrEmpty(treatments_mexpirationTextBox.Text))
((treatments)item).treatments_mexpiration = Convert.ToByte(treatments_mexpirationTextBox.Text);
else
((treatments)item).treatments_mexpiration = null;
}
/// <summary>
/// Update an item
/// </summary>
/// <param name="item"></param>
private void Update_tabTreatments(object item)
{
//update mexpiration
if (!String.IsNullOrEmpty(treatments_mexpirationTextBox.Text))
((treatments)item).treatments_mexpiration = Convert.ToByte(treatments_mexpirationTextBox.Text);
else
((treatments)item).treatments_mexpiration = null;
DGUIGHFData.Update<treatments, DentneDModel>(_dentnedModel.Treatments, item);
}
/// <summary>
/// Remove an item
/// </summary>
/// <param name="item"></param>
private void Remove_tabTreatments(object item)
{
DGUIGHFData.Remove<treatments, DentneDModel>(_dentnedModel.Treatments, item);
}
/// <summary>
/// Unset taxes_id
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button_tabTreatments_unsettaxesid_Click(object sender, EventArgs e)
{
taxes_idComboBox.SelectedIndex = -1;
}
#endregion
#region tabTreatmentsPrices
/// <summary>
/// Get tab list DataSource
/// </summary>
/// <returns></returns>
private object GetDataSourceList_tabTreatmentsPrices()
{
object ret = null;
//get current treatment
int treatments_id = -1;
if (vTreatmentsBindingSource.Current != null)
{
treatments_id = (((DataRowView)vTreatmentsBindingSource.Current).Row).Field<int>("treatments_id");
}
//get treatments
List<treatmentsprices> treatmentspricesl = new List<treatmentsprices>();
if (comboBox_tabTreatmentsPrices_filterPriceslists.SelectedIndex != -1 && comboBox_tabTreatmentsPrices_filterPriceslists.SelectedIndex != 0)
{
int treatmentspriceslists_id = Convert.ToInt32(comboBox_tabTreatmentsPrices_filterPriceslists.SelectedValue);
treatmentspricesl = _dentnedModel.TreatmentsPrices.List(r => r.treatments_id == treatments_id && r.treatmentspriceslists_id == treatmentspriceslists_id).ToList();
}
else
treatmentspricesl = _dentnedModel.TreatmentsPrices.List(r => r.treatments_id == treatments_id).ToList();
IEnumerable<VTreatmentsPrices> vTreatmentsPrices =
treatmentspricesl.Select(
r => new VTreatmentsPrices
{
treatmentsprices_id = r.treatmentsprices_id,
price = (double)r.treatmentsprices_price,
pricelist = _dentnedModel.TreatmentsPricesLists.Find(r.treatmentspriceslists_id).treatmentspriceslists_name
}).ToList();
ret = DGDataTableUtils.ToDataTable<VTreatmentsPrices>(vTreatmentsPrices);
return ret;
}
/// <summary>
/// Load the tab DataSource
/// </summary>
/// <returns></returns>
private object GetDataSourceEdit_tabTreatmentsPrices()
{
return DGUIGHFData.LoadEntityFromCurrentBindingSource<treatmentsprices, DentneDModel>(_dentnedModel.TreatmentsPrices, vTreatmentsPricesBindingSource, new string[] { "treatmentsprices_id" });
}
/// <summary>
/// Do actions after Save
/// </summary>
/// <param name="item"></param>
private void AfterSaveAction_tabTreatmentsPrices(object item)
{
DGUIGHFData.SetBindingSourcePosition<treatmentsprices, DentneDModel>(_dentnedModel.TreatmentsPrices, item, vTreatmentsPricesBindingSource);
}
/// <summary>
/// Add an item
/// </summary>
/// <param name="item"></param>
private void Add_tabTreatmentsPrices(object item)
{
DGUIGHFData.Add<treatmentsprices, DentneDModel>(_dentnedModel.TreatmentsPrices, item);
}
/// <summary>
/// Update an item
/// </summary>
/// <param name="item"></param>
private void Update_tabTreatmentsPrices(object item)
{
DGUIGHFData.Update<treatmentsprices, DentneDModel>(_dentnedModel.TreatmentsPrices, item);
}
/// <summary>
/// Remove an item
/// </summary>
/// <param name="item"></param>
private void Remove_tabTreatmentsPrices(object item)
{
DGUIGHFData.Remove<treatmentsprices, DentneDModel>(_dentnedModel.TreatmentsPrices, item);
}
/// <summary>
/// New tab button handler
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button_tabTreatmentsPrices_new_Click(object sender, EventArgs e)
{
if (vTreatmentsBindingSource.Current != null)
{
if (AddClick(tabElement_tabTreatmentsPrices))
{
((treatmentsprices)treatmentspricesBindingSource.Current).treatments_id = (((DataRowView)vTreatmentsBindingSource.Current).Row).Field<int>("treatments_id");
if (comboBox_tabTreatmentsPrices_filterPriceslists.SelectedIndex != -1 && comboBox_tabTreatmentsPrices_filterPriceslists.SelectedIndex != 0)
{
((treatmentsprices)treatmentspricesBindingSource.Current).treatmentspriceslists_id = Convert.ToInt32(comboBox_tabTreatmentsPrices_filterPriceslists.SelectedValue);
treatmentspriceslists_idComboBox.Enabled = false;
}
treatmentspricesBindingSource.ResetBindings(true);
}
}
}
/// <summary>
/// Treatments prices changed
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void comboBox_tabTreatmentsPrices_filterPriceslists_SelectedIndexChanged(object sender, EventArgs e)
{
if (IsBindingSourceLoading)
return;
ReloadTab(tabElement_tabTreatmentsPrices);
}
/// <summary>
/// Treatments lists changed
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void treatmentspriceslists_idComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
if (IsBindingSourceLoading)
return;
if (treatmentspriceslists_idComboBox.SelectedIndex != -1 && (tabElement_tabTreatmentsPrices.CurrentEditingMode == EditingMode.C || tabElement_tabTreatmentsPrices.CurrentEditingMode == EditingMode.U))
{
int treatments_id = -1;
if (vTreatmentsBindingSource.Current != null)
{
treatments_id = (((DataRowView)vTreatmentsBindingSource.Current).Row).Field<int>("treatments_id");
}
if (treatments_id != -1)
{
treatments treatments = _dentnedModel.Treatments.Find(treatments_id);
treatmentspriceslists treatmentspriceslist = _dentnedModel.TreatmentsPricesLists.Find(treatmentspriceslists_idComboBox.SelectedValue);
if (treatments != null && treatmentspriceslist != null)
{
((treatmentsprices)treatmentspricesBindingSource.Current).treatmentspriceslists_id = treatmentspriceslist.treatmentspriceslists_id;
((treatmentsprices)treatmentspricesBindingSource.Current).treatmentsprices_price = Math.Round(treatments.treatments_price * treatmentspriceslist.treatmentspriceslists_multiplier, 2);
}
treatmentspricesBindingSource.ResetBindings(true);
}
}
}
#endregion
private void button_tabTreatments_save_Click(object sender, EventArgs e)
{
}
private void treatments_codeTextBox_TextChanged(object sender, EventArgs e)
{
}
}
}
I would suggest reading up on Regular Expressions and download a Regex tool such as Expresso (http://www.ultrapico.com/expresso.htm), or use one of the various online Regex evaluation sites.
"^[A-Z0-9\-]{6}$"
This conflicts with what you are saying about "expecting 3 characters". This Regex will expect 6, and only 6 characters ranging from A-Z, 0-9, and-or a "-". The text message that is added to the errors collection may still say "3 characters" but that is a misleading message that needs to be updated. Whatever changes you do to the regular expression, you should also update the message behind language.text003, wherever that is coming from. (Resource file, database, etc.)
If the updated text box can accept any number of characters, but still needs to be A-Z, 0-9, and "-" then:
"^[A-Z0-9\-]*"
If you want to impose a maximum of 20 characters for example:
"^[A-Z0-9\-]{0,20}$"
If you want a minimum of 6 and maximum of 20:
"^[A-Z0-9\-]{6,20}$"
If you just want to accept any string and remove the character restrictions all-together, then delete that whole if block.
I have this code in front but I can't build a linked list with more than one element. I see that in the methode "einsetzenNach" the code block in the if statement will never executed. The reason is that the cursor will never get != 0
The code original was in Java.
I am thankful for any tips.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace EinfachVerketteteListe
{
class Program
{
static void Main(string[] args)
{
Liste myList = new Liste();
myList.einsetzenVor(1, "Nr01");
myList.einsetzenVor(2, "Nr02");
myList.einsetzenNach(2, "Nr02");
myList.einsetzenNach(3, "Nr03");
myList.inhalt(3);
myList.laenge();
myList.ToString();
}
}
Here is the Cell class
class Zelle
{
// Contents
public Object inhalt;
// Next cell
public Zelle next;
public Zelle(Object el)
{
inhalt = el;
}
public Zelle(Object el, Zelle z)
{
inhalt = el;
next = z;
}
public Zelle(Zelle z)
{
next = z;
}
}
Our custom list class
public class Liste
{
// Start element
private Zelle anfang;
// Current Element
private Zelle cursor;
/// <summary>
/// There are no more items in the list, start is null
/// </summary>
/// <returns>start == null</returns>
public Boolean IstLeer()
{
return anfang == null;
}
/// <summary>
/// Length of the list
/// </summary>
/// <returns>l = listlenght</returns>
public int laenge()
{
Zelle cur = anfang;
int l = 0;
while (cur != null)
{
l++;
cur = cur.next;
}
return l;
}
/// <summary>
/// Check of the declared position is valid
/// </summary>
/// <param name="p">Position</param>
/// <returns>true/false</returns>
public Boolean istGueltigePosition(int p)
{
return (p >= 1) && (p <= laenge() );
}
/// <summary>
///
/// </summary>
/// <param name="p">Set cursor on a specific position</param>
public void setzeCursor(int p)
{
cursor = null;
if (istGueltigePosition(p))
{
Zelle cur = anfang;
// cur.next is null. The reason is that there is only one element in the list
// How can I fix this block. However I assume the code will work.
// Maybe I handle something not in the correct order.
for (int i = 0; i < p; i++)
{ cur = cur.next; }
cursor = cur;
}
}
Maybe the Methode initCursor() is the answer to my understanding problem.
However I have no idea in which way I can use this methode to print out the first element.
/// <summary>
/// Initial Position Cursor
/// </summary>
public void initCursor()
{
cursor = anfang;
}
/// <summary>
/// Search for specific object and return it's index
/// </summary>
/// <param name="e">Zu findende Daten</param>
/// <returns>p = Index</returns>
public int suche(Object e)
{
cursor = null;
int p = 0, l = 0;
Zelle z = anfang;
while (z != null)
{
l++;
if ( z.inhalt == e )
{
p = l;
cursor = z;
break;
}
z = z.next;
}
return p;
}
/// <summary>
/// Insert cell after element p
/// </summary>
/// <param name="p">Position</param>
/// <param name="e">Daten</param>
public void einsetzenNach(int p, Object e)
{
setzeCursor(p);
This if statment will never get !=0
if (cursor != null)
{
Zelle z = new Zelle(e, cursor.next);
cursor.next = z;
}
}
/// <summary>
/// Insert cell after element p
/// </summary>
/// <param name="p">Position</param>
/// <param name="e">Daten</param>
public void einsetzenVor(int p, Object e)
{
if (p > 1) einsetzenNach(p-1,e);
else
{
// Insert at the beginning
Zelle z = new Zelle(e, anfang);
anfang = z;
}
}
public void loesche(int p)
{
if (istGueltigePosition(p))
{
if (p == 1) // Lösche 1. Object
anfang = anfang.next;
else
{
setzeCursor(p - 1);
cursor.next = cursor.next.next;
}
}
}
/// <summary>
/// Show the content
/// </summary>
/// <param name="p">position</param>
/// <returns></returns>
public Object inhalt(int p)
{
setzeCursor(p);
if (cursor == null) return null;
return cursor.inhalt;
}
/// <summary>
/// next cell/data
/// </summary>
/// <returns>Daten</returns>
public Object naechstes()
{
if (cursor == null) return null;
Object e = cursor.inhalt;
cursor = cursor.next;
return e;
}
}
}
Let's assume you added the first element successfully to the list and now you want to add the second element.
After checking for a valid position you set your current cell to start (Zelle cur = anfang;). After that you want to get to the position where you want to insert your object. But since it is your first element there are no following elements. So cur will always be null after the loop.
Since your list has not a zero-based index you should start your loop with the first index of your list. Try the following loop:
for (int i = 1; i < p; i++)
{
if (cur.next == null)
{
break;
}
cur = cur.next;
}
cursor = cur;
I am fairly new to Winforms, and I would like to know how to use a MaskedTextBox to ensure that only numerical values(decimals included) are entered by the user.
I have tried the masked feature using "/^[-+]?[0-9]+(.[0-9]+)?$/" and was not successful with that. What I want, even if with an ordinary textbox, is to allow only numerals/decimal values
Why not just use a NumericUpDown? Set your max and min values, number of decimal places, and away you go.
http://msdn.microsoft.com/en-us/library/system.windows.forms.numericupdown%28v=vs.90%29.aspx
Masks for the MaskedTextBox aren't regex patterns; they use their own syntax.
The pattern you want is probably something like "999,990.9999". This requires the user to enter at least one digit, but they can enter any number from 0 to 999,999.9999 and with up to 4 decimals precision, and will automatically insert the thousands separator when needed.
Another thing you can do, similar to what the MaskedTextBox itself does, is override OnKeyPress to reject any character entered that would cause a Regex not to match:
public class RegexTextBox:TextBox
{
[Category("Behavior")]
public string RegexPattern {get;set;}
protected override OnKeyPress(KeyPressEventArgs e)
{
if (!Regex.IsMatch(this.Text + e.KeyChar, RegexPattern)) e.Handled = true;
else base.OnKeyPress(e);
}
}
You have to be careful when defining the pattern, because it will only work if what's been entered so far matches the pattern. However, it will work in your case, if you use a pattern like "[0-9]{1,3}((,[0-9]{1,3})*(\.[0-9]*)?".
I adapted this NumericTextBox control: http://sanity-free.org/forum/viewtopic.php?pid=1205#p1205
If you want it apart of your toolbox, you'd probably create a new control based on a TextBox and paste the code in that link into the code section.
Here's my version of it. I don't know how much I've modified it as I've had it a long time.
NumericTextBox.Designer.cs:
using System.Windows.Forms;
namespace SeaRisenLib2.Controls
{
partial class NumericTextBox : TextBox
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
//this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
}
#endregion
}
}
NumericTextBox.cs
// From: http://sanity-free.org/forum/viewtopic.php?pid=1205#p1205
// modified it slightly
//
/******************************************************/
/* NULLFX FREE SOFTWARE LICENSE */
/******************************************************/
/* NumericTextBox Library */
/* by: Steve Whitley */
/* © 2005 NullFX Software */
/* */
/* NULLFX SOFTWARE DISCLAIMS ALL WARRANTIES, */
/* RESPONSIBILITIES, AND LIABILITIES ASSOCIATED WITH */
/* USE OF THIS CODE IN ANY WAY, SHAPE, OR FORM */
/* REGARDLESS HOW IMPLICIT, EXPLICIT, OR OBSCURE IT */
/* IS. IF THERE IS ANYTHING QUESTIONABLE WITH REGARDS */
/* TO THIS SOFTWARE BREAKING AND YOU GAIN A LOSS OF */
/* ANY NATURE, WE ARE NOT THE RESPONSIBLE PARTY. USE */
/* OF THIS SOFTWARE CREATES ACCEPTANCE OF THESE TERMS */
/* */
/* USE OF THIS CODE MUST RETAIN ALL COPYRIGHT NOTICES */
/* AND LICENSES (MEANING THIS TEXT). */
/* */
/******************************************************/
/* Changed by Carlos Montiers */
/* Decimal separator "." or "," depending on locale */
/* Constructor for numericTextBox whith or without */
/* negative range and number of decimals. */
/* Does not allow the entry of non-numeric character */
/* through alt + ascii code */
/* Permit use of tab key */
/* Version: 24-10-2008 */
/******************************************************/
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Text.RegularExpressions;
namespace SeaRisenLib2.Controls
{
public partial class NumericTextBox : TextBox
{
private const int WM_KEYDOWN = 0x0100;
private const int WM_PASTE = 0x0302;
private int decimalNumbers;
private bool hasNegatives;
private string format;
public delegate void D(NumericTextBox sender);
/// <summary>
/// Fired when Text changes
/// </summary>
public event D Changed = delegate { };
/// <summary>
/// Constructor of a NumericTextBox, with negative number and 2 decimals.
/// </summary>
public NumericTextBox()
: this(2, true)
{
}
/// <summary>
/// Constructor with parameters
/// </summary>
/// <param name="decimalNumbers">number of decimals</param>
/// <param name="hasNegatives">has negatives</param>
public NumericTextBox(int decimalNumbers, bool hasNegatives)
: base()
{
InitializeComponent();
DecimalNumbers = decimalNumbers;
HasNegatives = hasNegatives;
Format = Format;
}
/// <summary>
/// Property of decimalNumbers
/// </summary>
public int DecimalNumbers
{
get
{
return decimalNumbers;
}
set
{
decimalNumbers = value > 0 ? value : 0;
}
}
/// <summary>
/// Bindable Decimal Text
/// </summary>
public decimal DecimalText
{
get {
if(string.IsNullOrEmpty(Text))
return 0;
return Convert.ToDecimal(Text);
}
set { Text = value.ToString(); }
}
/// <summary>
/// The string text value of the numeric text, use DecimalText to get the numeric value.
/// </summary>
public override string Text
{
get { return base.Text; }
set
{
base.Text = value;
Changed(this);
}
}
/// <summary>
/// Property of hasNegatives
/// </summary>
public bool HasNegatives
{
get
{
return hasNegatives;
}
set
{
hasNegatives = value;
}
}
/// <summary>
/// Property of format
/// </summary>
public string Format
{
get
{
return format;
}
set
{
format = "^";
format += HasNegatives ? "(\\" + getNegativeSign() + "?)" : "";
format += "(\\d*)";
if (DecimalNumbers > 0)
{
format += "(\\" + getDecimalSeparator() + "?)";
for (int i = 1; i <= DecimalNumbers; i++)
{
format += "(\\d?)";
}
}
format += "$";
}
}
/// <summary>
/// Method PreProcessMessage
/// </summary>
/// <param name="msg">ref Message</param>
/// <returns>bool</returns>
public override bool PreProcessMessage(ref Message msg)
{
if (msg.Msg == WM_KEYDOWN)
{
Keys keys = (Keys)msg.WParam.ToInt32();
bool numbers = ModifierKeys != Keys.Shift
&& (keys >= Keys.D0 && keys <= Keys.D9
|| (keys >= Keys.NumPad0 && keys <= Keys.NumPad9));
bool dec = ModifierKeys != Keys.Shift
&& (keys == Keys.Decimal
|| keys == Keys.Oemcomma
|| keys == Keys.OemPeriod);
bool negativeSign = (keys == Keys.OemMinus && ModifierKeys != Keys.Shift)
|| keys == Keys.Subtract;
bool home = keys == Keys.Home;
bool end = keys == Keys.End;
bool ctrlZ = keys == Keys.Z && ModifierKeys == Keys.Control;
bool ctrlX = keys == Keys.X && ModifierKeys == Keys.Control;
bool ctrlC = keys == Keys.C && ModifierKeys == Keys.Control;
bool ctrlV = keys == Keys.V && ModifierKeys == Keys.Control;
bool del = keys == Keys.Delete;
bool bksp = keys == Keys.Back;
bool tab = keys == Keys.Tab;
bool arrows = keys == Keys.Up
|| keys == Keys.Down
|| keys == Keys.Left
|| keys == Keys.Right;
if (numbers || del || bksp || arrows || home || end
|| ctrlC || ctrlX || ctrlV || ctrlZ)
{
return false;
}
else
{
if (dec)
{
return DecimalNumbers <= 0;
}
else
{
if (negativeSign)
{
return !HasNegatives;
}
else
{
if (tab)
{
return base.PreProcessMessage(ref msg);
}
else
{
return true;
}
}
}
}
}
else
{
return base.PreProcessMessage(ref msg);
}
}
/// <summary>
/// Method WndProc
/// </summary>
/// <param name="m">ref Message</param>
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_PASTE)
{
IDataObject obj = Clipboard.GetDataObject();
string input = (string)obj.GetData(typeof(string));
string pasteText = getPosibleText(input);
if (!isValidadFormat(pasteText))
{
m.Result = (IntPtr)0;
return;
}
}
base.WndProc(ref m);
}
/// <summary>
/// Method OnKeyPress
/// </summary>
/// <param name="e">KeyPressEventArgs</param>
protected override void OnKeyPress(KeyPressEventArgs e)
{
base.OnKeyPress(e);
string keyInput = e.KeyChar.ToString();
string inputText = getPosibleText(keyInput);
if (Char.IsDigit(e.KeyChar)
|| keyInput.Equals(getDecimalSeparator())
|| keyInput.Equals(getNegativeSign()))
{
e.Handled = !isValidadFormat(inputText);
}
else if (e.KeyChar == '\b'
|| e.KeyChar == '\t'
|| keyInput.Equals(Keys.Delete.ToString())
|| keyInput.Equals(Keys.Home.ToString())
|| keyInput.Equals(Keys.End.ToString()))
{
//Allow backspace, tab, delete, home, end
}
else if (e.KeyChar == 26
|| e.KeyChar == 24
|| e.KeyChar == 3
|| e.KeyChar == 22)
{
// 26 : Allow Ctrl+Z | 24 : Allow Ctrl+X
// 3 : Allow Ctrl+C | 22 : Allow Ctrl+V
}
else
{
//Disallow
e.Handled = true;
}
}
/// <summary>
/// Method OnTextChanged
/// </summary>
/// <param name="e">System.EventArgs</param>
protected override void OnTextChanged(System.EventArgs e)
{
if (getFloatValue() < 0)
{
this.ForeColor = Color.Red;
}
else
{
this.ForeColor = Color.Black;
}
//If the decimal point is preceded by a no number is added zero
if (this.Text.StartsWith(getNegativeSign() + getDecimalSeparator()))
{
this.Text = getNegativeSign() + "0" + this.Text.Substring(1);
this.Select(3, 0);
}
else
{
if (this.Text.StartsWith(getDecimalSeparator()))
{
this.Text = "0" + this.Text;
this.Select(2, 0);
}
}
base.OnTextChanged(e);
}
/// <summary>
/// Method for validate text with format
/// </summary>
/// <param name="text">text</param>
/// <returns>is valid format</returns>
private bool isValidadFormat(string text)
{
return Regex.IsMatch(text, Format);
}
/// <summary>
/// Method for get deciamal separator
/// </summary>
/// <returns>Decimal Separator of current culture</returns>
private string getDecimalSeparator()
{
return System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator;
}
/// <summary>
/// Method for get negative sign
/// </summary>
/// <returns>Negative Sign of current culture</returns>
private string getNegativeSign()
{
return System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NegativeSign;
}
/// <summary>
/// Method for get posible resulting text for input text
/// </summary>
/// <param name="text">string with input text</param>
/// <returns>posible text</returns>
private string getPosibleText(string text)
{
string rText;
rText = this.Text.Substring(0, SelectionStart);
rText += text;
rText += this.Text.Substring(SelectionStart + SelectionLength);
return rText;
}
/// <summary>
/// Method for get int value of text
/// </summary>
/// <returns>int value</returns>
public int getIntValue()
{
try
{
return (int)getFloatValue();
}
catch
{
return 0;
}
}
/// <summary>
/// Method for get round int value of text
/// </summary>
/// <returns>round int value</returns>
public int getIntRoundValue()
{
try
{
return (int)Math.Round(getFloatValue());
}
catch
{
return 0;
}
}
/// <summary>
/// Method for get float value of text
/// </summary>
/// <returns>float value</returns>
public float getFloatValue()
{
try
{
return float.Parse(this.Text);
}
catch
{
return 0;
}
}
}
}
thanks , working code below.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;
namespace System.Windows.Forms {
public class RegexTextBox : TextBox {
[Category("Behavior")]
public string RegexPattern { get; set; }
private bool DelOrBack = false;
protected override void OnKeyDown(KeyEventArgs e) {
base.OnKeyDown(e);
if (e.KeyCode == Keys.Back || e.KeyCode == Keys.Delete) {
DelOrBack = true;
}
}
protected override void OnKeyPress(KeyPressEventArgs e) {
if (!Regex.IsMatch(this.Text + e.KeyChar, RegexPattern) && !DelOrBack) {
e.Handled = true;
}
else {
base.OnKeyPress(e);
}
DelOrBack = false;
}
}
public class NumericTextBox : RegexTextBox {
public NumericTextBox() {
RegexPattern = "^[0-9]+$";
}
}
}
I have seen threads on many sites regarding extending the gridview control so obviously this will be a duplicate. But I haven't found any that truly extend the control to the extent that you could have custom sorting (with header images), filtering by putting drop downs or textboxes in header columns (on a column by column basis) and custom paging (one that doesn't return all records but just returns the ones requested for the given page).
Are there any good tutorials that show the inner-workings of the gridview and how to override the proper functions? I've seen several snippets here and there but none seem to really work and explain things well.
Any links would be appreciated. Thanks!
I've extended the GridView control myself to allow sorting with images, custom paging (so you can select how many records per page from a drop-down) and a few other things. However, you won't be able to do custom paging that just returns the records for the requested page, as that is something your datasource needs to handle and not the GridView.
All I can really do is give you some code and hope it helps. It's pretty old code (pre C#3.0) but may be of some use:
First of all here's the custom GridView control that extends the standard GridView:
using System;
using System.Collections;
using System.Drawing;
using System.Web.UI.WebControls;
using Diplo.WebControls.DataControls.PagerTemplates;
using Image=System.Web.UI.WebControls.Image;
namespace Diplo.WebControls.DataControls
{
/// <summary>
/// Extended <see cref="GridView"/> with some additional cool properties
/// </summary>
public class DiploGridView : GridView
{
#region Properties
/// <summary>
/// Gets or sets a value indicating whether a sort graphic is shown in column headings
/// </summary>
/// <value><c>true</c> if sort graphic is displayed; otherwise, <c>false</c>.</value>
public bool EnableSortGraphic
{
get
{
object o = ViewState["EnableSortGraphic"];
if (o != null)
{
return (bool)o;
}
return true;
}
set
{
ViewState["EnableSortGraphic"] = value;
}
}
/// <summary>
/// Gets or sets the sort ascending image when <see cref="EnableSortGraphic"/> is <c>true</c>
/// </summary>
public string SortAscendingImage
{
get
{
object o = ViewState["SortAscendingImage"];
if (o != null)
{
return (string)o;
}
return Page.ClientScript.GetWebResourceUrl(GetType(), SharedWebResources.ArrowUpImage);
}
set
{
ViewState["SortAscendingImage"] = value;
}
}
/// <summary>
/// Gets or sets the sort descending image <see cref="EnableSortGraphic"/> is <c>true</c>
/// </summary>
public string SortDescendingImage
{
get
{
object o = ViewState["SortDescendingImage"];
if (o != null)
{
return (string)o;
}
return Page.ClientScript.GetWebResourceUrl(GetType(), SharedWebResources.ArrowDownImage);
}
set
{
ViewState["SortDescendingImage"] = value;
}
}
/// <summary>
/// Gets or sets the custom pager settings mode.
/// </summary>
public CustomPagerMode CustomPagerSettingsMode
{
get
{
object o = ViewState["CustomPagerSettingsMode"];
if (o != null)
{
return (CustomPagerMode)o;
}
return CustomPagerMode.None;
}
set
{
ViewState["CustomPagerSettingsMode"] = value;
}
}
/// <summary>
/// Gets or sets a value indicating whether the columns in the grid can be re-sized in the UI
/// </summary>
/// <value><c>true</c> if column resizing is allowed; otherwise, <c>false</c>.</value>
public bool AllowColumnResizing
{
get
{
object o = ViewState["AllowColumnResizing"];
if (o != null)
{
return (bool)o;
}
return false;
}
set
{
ViewState["AllowColumnResizing"] = value;
}
}
/// <summary>
/// Gets or sets the highlight colour for the row
/// </summary>
public Color RowStyleHighlightColour
{
get
{
object o = ViewState["RowStyleHighlightColour"];
if (o != null)
{
return (Color)o;
}
return Color.Empty;
}
set
{
ViewState["RowStyleHighlightColour"] = value;
}
}
#endregion Properties
#region Enums
/// <summary>
/// Represents additional custom paging modes
/// </summary>
public enum CustomPagerMode
{
/// <summary>
/// No custom paging mode
/// </summary>
None,
/// <summary>
/// Shows the rows drop-down list <i>and</i> the previous and next buttons
/// </summary>
RowsPagePreviousNext,
/// <summary>
/// Only shows the previous and next buttons
/// </summary>
PagePreviousNext
}
#endregion
#region Overridden Events
/// <summary>
/// Initializes the pager row displayed when the paging feature is enabled.
/// </summary>
/// <param name="row">A <see cref="T:System.Web.UI.WebControls.GridViewRow"></see> that represents the pager row to initialize.</param>
/// <param name="columnSpan">The number of columns the pager row should span.</param>
/// <param name="pagedDataSource">A <see cref="T:System.Web.UI.WebControls.PagedDataSource"></see> that represents the data source.</param>
protected override void InitializePager(GridViewRow row, int columnSpan, PagedDataSource pagedDataSource)
{
switch (CustomPagerSettingsMode)
{
case CustomPagerMode.RowsPagePreviousNext:
PagerTemplate = new RowsPagePreviousNext(pagedDataSource, this);
break;
case CustomPagerMode.PagePreviousNext:
PagerTemplate = new PagePreviousNext(pagedDataSource, this);
break;
case CustomPagerMode.None:
break;
default:
break;
}
base.InitializePager(row, columnSpan, pagedDataSource);
}
/// <summary>
/// Raises the <see cref="E:System.Web.UI.Control.PreRender"></see> event.
/// </summary>
/// <param name="e">An <see cref="T:System.EventArgs"></see> that contains the event data.</param>
protected override void OnPreRender(EventArgs e)
{
if (AllowColumnResizing && Visible)
{
string vars = String.Format("var _DiploGridviewId = '{0}';\n", ClientID);
if (!Page.ClientScript.IsClientScriptBlockRegistered("Diplo_GridViewVars"))
{
Page.ClientScript.RegisterClientScriptBlock(GetType(), "Diplo_GridViewVars", vars, true);
}
Page.ClientScript.RegisterClientScriptInclude("Diplo_GridView.js",
Page.ClientScript.GetWebResourceUrl(GetType(), "Diplo.WebControls.SharedWebResources.Diplo_GridView_Resize.js"));
}
base.OnPreRender(e);
}
/// <summary>
/// Raises the <see cref="E:System.Web.UI.WebControls.GridView.RowCreated"></see> event.
/// </summary>
/// <param name="e">A <see cref="T:System.Web.UI.WebControls.GridViewRowEventArgs"></see> that contains event data.</param>
protected override void OnRowCreated(GridViewRowEventArgs e)
{
if (EnableSortGraphic)
{
if (!((e.Row == null)) && e.Row.RowType == DataControlRowType.Header)
{
foreach (TableCell cell in e.Row.Cells)
{
if (cell.HasControls())
{
LinkButton button = ((LinkButton)(cell.Controls[0]));
if (!((button == null)))
{
Image image = new Image();
image.ImageUrl = "images/default.gif";
image.ImageAlign = ImageAlign.Baseline;
if (SortExpression == button.CommandArgument)
{
image.ImageUrl = SortDirection == SortDirection.Ascending ? SortAscendingImage : SortDescendingImage;
Literal space = new Literal();
space.Text = " ";
cell.Controls.Add(space);
cell.Controls.Add(image);
}
}
}
}
}
}
if (RowStyleHighlightColour != Color.Empty)
{
if (e.Row != null)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
e.Row.Attributes.Add("onmouseover", String.Format("this.style.backgroundColor='{0}'", ColorTranslator.ToHtml(RowStyleHighlightColour)));
e.Row.Attributes.Add("onmouseout", "this.style.backgroundColor=''");
}
}
}
base.OnRowCreated(e);
}
/// <summary>
/// Creates the control hierarchy that is used to render a composite data-bound control based on the values that are stored in view state.
/// </summary>
protected override void CreateChildControls()
{
base.CreateChildControls();
CheckShowPager();
}
private void CheckShowPager()
{
if (CustomPagerSettingsMode != CustomPagerMode.None && AllowPaging)
{
if (TopPagerRow != null)
{
TopPagerRow.Visible = true;
}
if (BottomPagerRow != null)
{
BottomPagerRow.Visible = true;
}
}
}
/// <summary>
/// Creates the control hierarchy used to render the <see cref="T:System.Web.UI.WebControls.GridView"></see> control using the specified data source.
/// </summary>
/// <param name="dataSource">An <see cref="T:System.Collections.IEnumerable"></see> that contains the data source for the <see cref="T:System.Web.UI.WebControls.GridView"></see> control.</param>
/// <param name="dataBinding">true to indicate that the child controls are bound to data; otherwise, false.</param>
/// <returns>The number of rows created.</returns>
protected override int CreateChildControls(IEnumerable dataSource, bool dataBinding)
{
int i = base.CreateChildControls(dataSource, dataBinding);
CheckShowPager();
return i;
}
#endregion Overridden Events
}
}
Then there is a custom paging class that is used as a paging template:
using System;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Web.UI;
namespace Diplo.WebControls.DataControls.PagerTemplates
{
/// <summary>
/// Paging template for the <see cref="DiploGridView"/>
/// </summary>
public class RowsPagePreviousNext : ITemplate
{
readonly PagedDataSource _pagedDataSource;
readonly DiploGridView DiploGridView;
/// <summary>
/// Initializes a new instance of the <see cref="RowsPagePreviousNext"/> class.
/// </summary>
/// <param name="pagedDataSource">The <see cref="PagedDataSource"/>.</param>
/// <param name="DiploGrid">A reference to the <see cref="DiploGridView"/>.</param>
public RowsPagePreviousNext(PagedDataSource pagedDataSource, DiploGridView DiploGrid)
{
_pagedDataSource = pagedDataSource;
DiploGridView = DiploGrid;
}
/// <summary>
/// When implemented by a class, defines the <see cref="T:System.Web.UI.Control"></see> object that child controls and templates belong to. These child controls are in turn defined within an inline template.
/// </summary>
/// <param name="container">The <see cref="T:System.Web.UI.Control"></see> object to contain the instances of controls from the inline template.</param>
void ITemplate.InstantiateIn(Control container)
{
Literal space = new Literal();
space.Text = " ";
HtmlGenericControl divLeft = new HtmlGenericControl("div");
divLeft.Style.Add("float", "left");
divLeft.Style.Add(HtmlTextWriterStyle.Width, "25%");
Label lb = new Label();
lb.Text = "Show rows: ";
divLeft.Controls.Add(lb);
DropDownList ddlPageSize = new DropDownList();
ListItem item;
ddlPageSize.AutoPostBack = true;
ddlPageSize.ToolTip = "Select number of rows per page";
int max = (_pagedDataSource.DataSourceCount < 50) ? _pagedDataSource.DataSourceCount : 50;
int i;
const int increment = 5;
bool alreadySelected = false;
for (i = increment; i <= max; i = i + increment)
{
item = new ListItem(i.ToString());
if (i == _pagedDataSource.PageSize)
{
item.Selected = true;
alreadySelected = true;
}
ddlPageSize.Items.Add(item);
}
item = new ListItem("All", _pagedDataSource.DataSourceCount.ToString());
if (_pagedDataSource.DataSourceCount == _pagedDataSource.PageSize && alreadySelected == false)
{
item.Selected = true;
alreadySelected = true;
}
if (_pagedDataSource.DataSourceCount > (i - increment) && alreadySelected == false)
{
item.Selected = true;
}
ddlPageSize.Items.Add(item);
ddlPageSize.SelectedIndexChanged += new EventHandler(ddlPageSize_SelectedIndexChanged);
divLeft.Controls.Add(ddlPageSize);
HtmlGenericControl divRight = new HtmlGenericControl("div");
divRight.Style.Add("float", "right");
divRight.Style.Add(HtmlTextWriterStyle.Width, "75%");
divRight.Style.Add(HtmlTextWriterStyle.TextAlign, "right");
Literal lit = new Literal();
lit.Text = String.Format("Found {0} record{1}. Page ",
_pagedDataSource.DataSourceCount,
(_pagedDataSource.DataSourceCount == 1) ? String.Empty : "s" );
divRight.Controls.Add(lit);
TextBox tbPage = new TextBox();
tbPage.ToolTip = "Enter page number";
tbPage.Columns = 2;
tbPage.MaxLength = 3;
tbPage.Text = (_pagedDataSource.CurrentPageIndex + 1).ToString();
tbPage.CssClass = "pagerTextBox";
tbPage.AutoPostBack = true;
tbPage.TextChanged += new EventHandler(tbPage_TextChanged);
divRight.Controls.Add(tbPage);
if (_pagedDataSource.PageCount < 2)
tbPage.Enabled = false;
lit = new Literal();
lit.Text = " of " + _pagedDataSource.PageCount;
divRight.Controls.Add(lit);
divRight.Controls.Add(space);
Button btn = new Button();
btn.Text = "";
btn.CommandName = "Page";
btn.CommandArgument = "Prev";
btn.SkinID = "none";
btn.Enabled = !_pagedDataSource.IsFirstPage;
btn.CssClass = (btn.Enabled) ? "buttonPreviousPage" : "buttonPreviousPageDisabled";
if (btn.Enabled)
btn.ToolTip = "Previous page";
divRight.Controls.Add(btn);
btn = new Button();
btn.Text = "";
btn.CommandName = "Page";
btn.CommandArgument = "Next";
btn.SkinID = "none";
btn.CssClass = "buttonNext";
btn.Enabled = !_pagedDataSource.IsLastPage;
btn.CssClass = (btn.Enabled) ? "buttonNextPage" : "buttonNextPageDisabled";
if (btn.Enabled)
btn.ToolTip = "Next page";
divRight.Controls.Add(btn);
container.Controls.Add(divLeft);
container.Controls.Add(divRight);
}
/// <summary>
/// Handles the TextChanged event of the tbPage control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
void tbPage_TextChanged(object sender, EventArgs e)
{
TextBox tb = sender as TextBox;
if (tb != null)
{
int page;
if (int.TryParse(tb.Text, out page))
{
if (page <= _pagedDataSource.PageCount && page > 0)
{
DiploGridView.PageIndex = page - 1;
}
}
}
}
/// <summary>
/// Handles the SelectedIndexChanged event of the ddlPageSize control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
void ddlPageSize_SelectedIndexChanged(object sender, EventArgs e)
{
DropDownList list = sender as DropDownList;
if (list != null) DiploGridView.PageSize = Convert.ToInt32(list.SelectedValue);
}
}
}
I can't really talk you through it as server controls are complex, I just hope it gives you some help.