Example T315168
Visible to All Users

WinForms TokenEdit - Create checked tokens

This example creates a custom token editor (CustomTokenEdit) that displays a checkbox in tokens.

WinForms TokenEdit - Display a checkbox in a token

You can use the custom token editor as a standalone editor or as a cell editor in data-aware controls (for example, Data Grid, TreeList).

Custom Token Cell Editor - WinForms Data Grid

Tokens are of the CustomTokenEditToken type. This class inherits base functionality from the TokenEditToken class and introduces a new Checked property. When the checked state of a token changes, the editor raises the RepositoryItemCustomTokenEdit.TokenCheckedChanged event.

Files to Review

See Also

Does this example address your development requirements/objectives?

(you will be redirected to DevExpress.com to submit your response)

Example Code

TokenEdit_Glyph_InEndOfToken/CustomTokenEdit/CustomTokenEdit.cs
C#
using DevExpress.XtraEditors; using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; namespace TokenEdit_Glyph_InEndOfToken.CustomTokenEdit { [ToolboxItem(true)] public class CustomTokenEdit : TokenEdit { static CustomTokenEdit() { RepositoryItemCustomTokenEdit.Register(); } public CustomTokenEdit() { (Painter as CustomTokenEditPainter).SetEditor(this); } public override string EditorTypeName { get { return RepositoryItemCustomTokenEdit.EditorName; } } [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] public new RepositoryItemCustomTokenEdit Properties { get { return base.Properties as RepositoryItemCustomTokenEdit; } } public void Repaint() { base.LayoutChanged(); } protected override TokenEditHandler CreateHandler() { return new CustomTokenEdithandler(this); } public CustomTokenEditToken CheckedItem { get { return base.CheckedItem as CustomTokenEditToken;} } public CustomTokenEditCheckedItemCollection CheckedItems { get { return base.CheckedItems as CustomTokenEditCheckedItemCollection; } } public CustomTokenEditSelectedItemCollection SelectedItems { get { return base.SelectedItems as CustomTokenEditSelectedItemCollection; } } } }
TokenEdit_Glyph_InEndOfToken/CustomTokenEdit/CustomTokenEditCheckedItemCollection.cs
C#
using DevExpress.XtraEditors; using System; using System.Collections.Generic; using System.Linq; using DevExpress.XtraEditors.Repository; namespace TokenEdit_Glyph_InEndOfToken.CustomTokenEdit { public class CustomTokenEditCheckedItemCollection : TokenEditCheckedItemCollection { public CustomTokenEditCheckedItemCollection(RepositoryItemTokenEdit properties) : base(properties) { } public CustomTokenEditToken this[int index] { get { return (CustomTokenEditToken)InnerList[index]; } } } }
TokenEdit_Glyph_InEndOfToken/CustomTokenEdit/CustomTokenEdithandler.cs
C#
using DevExpress.XtraEditors; using DevExpress.XtraEditors.ViewInfo; using System; using System.Collections.Generic; using System.Linq; namespace TokenEdit_Glyph_InEndOfToken.CustomTokenEdit { public class CustomTokenEdithandler : TokenEditHandler { public CustomTokenEdithandler(TokenEdit tokenEdit) : base(tokenEdit) { } protected override void OnTokenClick(TokenEditHitInfo hitInfo) { ChangeCheckedIfRequired(hitInfo); base.OnTokenClick(hitInfo); } private void ChangeCheckedIfRequired(TokenEditHitInfo hitInfo) { CustomTokenEditHitInfo hInfo = hitInfo as CustomTokenEditHitInfo; if (hInfo.IsInCheckBox) (hitInfo.HitObject as CustomTokenEditTokenInfo).ChangeChecked(); } } }
TokenEdit_Glyph_InEndOfToken/CustomTokenEdit/CustomTokenEditHitInfo.cs
C#
using DevExpress.XtraEditors.ViewInfo; using System; using System.Collections.Generic; using System.Linq; using System.Drawing; namespace TokenEdit_Glyph_InEndOfToken.CustomTokenEdit { public class CustomTokenEditHitInfo : TokenEditHitInfo { public CustomTokenEditHitInfo() { } public CustomTokenEditHitInfo(Point pt) : base(pt) { } public void ResetHitTest(TokenEditHitTest ht ) { SetHitTest(ht); } public void ResetHitObject(TokenEditTokenInfo obj) { SetHitObject(obj); } public bool IsInCheckBox { get; private set; } public void InCheckBox(bool val) { IsInCheckBox = val; } } }
TokenEdit_Glyph_InEndOfToken/CustomTokenEdit/CustomTokenEditPainter.cs
C#
using DevExpress.Skins; using DevExpress.Utils; using DevExpress.Utils.Drawing; using DevExpress.XtraEditors; using DevExpress.XtraEditors.Drawing; using DevExpress.XtraEditors.ViewInfo; using System; using System.Collections.Generic; using System.Drawing; using System.Linq; namespace TokenEdit_Glyph_InEndOfToken.CustomTokenEdit { public class CustomTokenEditPainter : TokenEditPainter { CustomTokenEdit editor; public void SetEditor(CustomTokenEdit _editor) { editor = _editor; } protected override void DoDrawGlyph(ControlGraphicsInfoArgs info, TokenEditTokenInfo tokenInfo) { base.DoDrawGlyph(info, tokenInfo); if (editor.Properties.CheckBoxSkinElement != null) { int index = 0; CustomTokenEditTokenInfo customTokenInfo = tokenInfo as CustomTokenEditTokenInfo; int offset = customTokenInfo.Checked == true ? 4 : 0; Rectangle rect = customTokenInfo.CheckBoxGlyphBounds; Rectangle r = new Rectangle(rect.X + (int)info.Graphics.ClipBounds.X, rect.Y + (int)info.Graphics.ClipBounds.Y, rect.Width, rect.Height); SkinElementInfo skinElementInfo = new SkinElementInfo(editor.Properties.CheckBoxSkinElement, r); switch (customTokenInfo.CheckBoxState) { case ObjectState.Normal: index = offset; break; case ObjectState.Hot: index = offset + 1; break; case ObjectState.Hot | ObjectState.Pressed: index = offset + 2; break; } skinElementInfo.ImageIndex = index; ImageCollection imageCollection = editor.Properties.CheckBoxSkinElement.Image.GetImages(); info.Graphics.DrawImage(imageCollection.Images[index], new Rectangle(rect.X + (int)info.Graphics.ClipBounds.X, rect.Y + (int)info.Graphics.ClipBounds.Y, rect.Width, rect.Height)); ObjectPainter.DrawObject(info.Cache, SkinElementPainter.Default, skinElementInfo); } } } }
TokenEdit_Glyph_InEndOfToken/CustomTokenEdit/CustomTokenEditSelectedItemCollection.cs
C#
using DevExpress.XtraEditors; using System; using System.Collections.Generic; using System.Linq; using DevExpress.XtraEditors.Repository; namespace TokenEdit_Glyph_InEndOfToken.CustomTokenEdit { public class CustomTokenEditSelectedItemCollection : TokenEditSelectedItemCollection { public CustomTokenEditSelectedItemCollection(RepositoryItemTokenEdit properties) : base(properties) { } public CustomTokenEditToken this[int index] { get { return (CustomTokenEditToken)InnerList[index]; } } } }
TokenEdit_Glyph_InEndOfToken/CustomTokenEdit/CustomTokenEditToken.cs
C#
using DevExpress.XtraEditors; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace TokenEdit_Glyph_InEndOfToken.CustomTokenEdit { public class CustomTokenEditToken : TokenEditToken { public CustomTokenEditToken() { } public CustomTokenEditToken(object value) : base(value) { } public CustomTokenEditToken(string description, object value, RepositoryItemCustomTokenEdit _Properties) : base(description, value) { Properties = _Properties; } readonly RepositoryItemCustomTokenEdit Properties; protected bool _checked; protected internal bool needRepaint = true; public bool Checked { get { return _checked; } set { if (_checked != value) { _checked = value; OnCheckedChanged(); } } } void OnCheckedChanged() { Properties.OnTokenCheckedChanged(this, needRepaint); needRepaint = true; } } }
TokenEdit_Glyph_InEndOfToken/CustomTokenEdit/CustomTokenEditTokenInfo.cs
C#
using DevExpress.XtraEditors.ViewInfo; using System; using System.Collections.Generic; using System.Linq; using DevExpress.XtraEditors; using System.Drawing; using DevExpress.Utils.Drawing; namespace TokenEdit_Glyph_InEndOfToken.CustomTokenEdit { public class CustomTokenEditTokenInfo : TokenEditTokenInfo { public CustomTokenEditTokenInfo(TokenEditToken token) : base(token) { } public CustomTokenEditTokenInfo(TokenEditToken token, Dictionary<TokenEditToken, Rectangle> _checkBoxBounds, CustomTokenEditViewInfo _viewInfo) : base(token) { checkBoxBounds = _checkBoxBounds; viewInfo = _viewInfo; } public CustomTokenEditToken CustomToken { get { return base.Token as CustomTokenEditToken; } } readonly Dictionary<TokenEditToken, Rectangle> checkBoxBounds; public Rectangle CheckBoxGlyphBounds { get { return checkBoxBounds[CustomToken]; } } readonly CustomTokenEditViewInfo viewInfo; public bool Checked { get { return CustomToken.Checked; } } public void ChangeChecked() { CustomToken.needRepaint = false; CustomToken.Checked = !CustomToken.Checked; } ObjectState checkBoxState; public ObjectState CheckBoxState { get { return checkBoxState; } set { if (checkBoxState != value) { checkBoxState = value; OnCheckBoxStateChanged(); } } } void OnCheckBoxStateChanged() { viewInfo.InvalidateCheckBox(); } } }
TokenEdit_Glyph_InEndOfToken/CustomTokenEdit/CustomTokenEditViewInfo.cs
C#
using DevExpress.XtraEditors.ViewInfo; using System; using System.Collections.Generic; using System.Linq; using DevExpress.XtraEditors.Repository; using System.Drawing; using DevExpress.Utils.Drawing; using System.Windows.Forms; using DevExpress.XtraEditors; namespace TokenEdit_Glyph_InEndOfToken.CustomTokenEdit { public class CustomTokenEditViewInfo : TokenEditViewInfo { public CustomTokenEditViewInfo(RepositoryItem item) : base(item) { checkBoxBounds = new Dictionary<TokenEditToken, Rectangle>(); } readonly Dictionary<TokenEditToken, Rectangle> checkBoxBounds; protected override Rectangle CalcBounds(Point topPt, TokenEditToken token) { Rectangle rect = base.CalcBounds(topPt, token); Rectangle temp = CalcGlyphBounds(token, rect); checkBoxBounds[token] = new Rectangle(rect.Right, temp.Top, temp.Width, temp.Height); rect.Width += CalcGlyphWidth(token) + ItemContentMargin; return rect; } protected override void UpdateTokenState(TokenEditTokenInfo tokenInfo) { base.UpdateTokenState(tokenInfo); if (!Item.ReadOnly) { Point pt = OwnerControl != null ? OwnerControl.PointToClient(Control.MousePosition) : MousePosition; CustomTokenEditTokenInfo info = tokenInfo as CustomTokenEditTokenInfo; if (info.CheckBoxGlyphBounds.Contains(pt)) { info.CheckBoxState = ObjectState.Hot; if ((Control.MouseButtons & MouseButtons.Left) != 0) info.CheckBoxState |= ObjectState.Pressed; } else { info.CheckBoxState = ObjectState.Normal; } } } protected internal void InvalidateCheckBox() { DoInvalidate(); } protected override TokenEditTokenInfo CreateTokenEditTokenInfo(TokenEditToken token) { CustomTokenEditTokenInfo info = new CustomTokenEditTokenInfo(token, checkBoxBounds, this); return info; } protected override EditHitInfo CreateHitInfo(Point p) { return new CustomTokenEditHitInfo(p); } public override EditHitInfo CalcHitInfo(Point pt) { CustomTokenEditHitInfo hi = CreateHitInfo(pt) as CustomTokenEditHitInfo; if(!Bounds.Contains(pt)) return hi; foreach(CustomTokenEditTokenInfo tokenInfo in VisibleItems) { if(tokenInfo.Bounds.Contains(pt)) { hi.ResetHitObject(tokenInfo); hi.ResetHitTest(TokenEditHitTest.Link); hi.InCheckBox(false); if (tokenInfo.CheckBoxGlyphBounds.Contains(pt)) hi.InCheckBox(true); if(tokenInfo.GlyphBounds.Contains(pt)) hi.ResetHitTest(TokenEditHitTest.Glyph); return hi; } } if(ContentRect.Contains(pt)) hi.ResetHitTest(TokenEditHitTest.EditorRect); return hi; } } }
TokenEdit_Glyph_InEndOfToken/CustomTokenEdit/RepositoryItemCustomTokenEdit.cs
C#
using DevExpress.Skins; using DevExpress.Utils; using DevExpress.XtraEditors; using DevExpress.XtraEditors.Registrator; using DevExpress.XtraEditors.Repository; using System; using System.Collections.Generic; using System.Linq; namespace TokenEdit_Glyph_InEndOfToken.CustomTokenEdit { [UserRepositoryItem("Register")] public class RepositoryItemCustomTokenEdit : RepositoryItemTokenEdit { static RepositoryItemCustomTokenEdit() { Register(); } public RepositoryItemCustomTokenEdit() { checkBoxCollection = GetCheckBoxImages(); } internal const string EditorName = "CustomTokenEdit"; public static void Register() { EditorRegistrationInfo.Default.Editors.Add(new EditorClassInfo(EditorName, typeof(CustomTokenEdit), typeof(RepositoryItemCustomTokenEdit), typeof(CustomTokenEditViewInfo), new CustomTokenEditPainter(), true, null)); } public override string EditorTypeName { get { return EditorName; } } readonly SkinElement checkBoxCollection; public SkinElement CheckBoxSkinElement { get { return checkBoxCollection; } } protected virtual SkinElement GetCheckBoxImages() { Skin skin = EditorsSkins.GetSkin(DevExpress.LookAndFeel.UserLookAndFeel.Default); SkinElement skinElement = skin["CheckBox"]; if (skinElement == null) return null; return skinElement; } protected override TokenEditCheckedItemCollection CreateCheckedItemCollection() { return new CustomTokenEditCheckedItemCollection(this); } protected override TokenEditSelectedItemCollection CreateSelectedItemCollection() { return new CustomTokenEditSelectedItemCollection(this); } protected override TokenEditToken CreateTokenInstance(string description, object value, bool autoPopulated) { CustomTokenEditToken token = new CustomTokenEditToken(description, value, this as RepositoryItemCustomTokenEdit); return token; } public event EventHandler<TokenCheckedChangedEventArgs> TokenCheckedChanged; protected internal void OnTokenCheckedChanged(CustomTokenEditToken token, bool repaint) { RepaintEditIfRequired(repaint); RaiseTokenCheckedChanged(token); } private void RaiseTokenCheckedChanged(CustomTokenEditToken token) { EventHandler<TokenCheckedChangedEventArgs> handler = TokenCheckedChanged; if (handler != null) handler(this, new TokenCheckedChangedEventArgs(token)); } private void RepaintEditIfRequired(bool repaint) { CustomTokenEdit edit = OwnerEdit as CustomTokenEdit; if (repaint && edit != null) edit.Repaint(); } } }
TokenEdit_Glyph_InEndOfToken/CustomTokenEdit/TokenCheckedChangedEventArgs.cs
C#
using System; using System.Collections.Generic; using System.Linq; namespace TokenEdit_Glyph_InEndOfToken.CustomTokenEdit { public class TokenCheckedChangedEventArgs : EventArgs { public TokenCheckedChangedEventArgs(CustomTokenEditToken _token) { Token = _token; } public CustomTokenEditToken Token { get; private set; } } }
TokenEdit_Glyph_InEndOfToken/Form1.cs
C#
using DevExpress.XtraEditors; using System; using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; using TokenEdit_Glyph_InEndOfToken.CustomTokenEdit; namespace TokenEdit_Glyph_InEndOfToken { public partial class Form1 : XtraForm { public Form1() { InitializeComponent(); InitToken(); InitGridControl(); } private void InitToken() { tokenEdit1.Properties.ValidateToken += tokenEdit1_ValidateToken; tokenEdit1.EditValue = "test@mail.com,test@test.com,test@microsoft.com"; tokenEdit1.Properties.TokenCheckedChanged += TokenCheckedChanged; } private void InitGridControl() { RepositoryItemCustomTokenEdit edit = new RepositoryItemCustomTokenEdit(); edit.Separators.AddRange(new string[] { "," }); edit.EditMode = TokenEditMode.Manual; edit.ValidateToken += tokenEdit1_ValidateToken; edit.TokenCheckedChanged += TokenCheckedChanged; List<Test> lst = new List<Test>(); for (int i = 0; i < 10; i++) lst.Add(new Test() { Token = string.Format("test{0}@mail.com", i) }); gridControl1.DataSource = lst; gridControl1.RepositoryItems.Add(edit); gridView1.Columns[0].ColumnEdit = edit; } readonly Regex MailRegex = new Regex(@"^[-a-z0-9!#$%&'*+/=?^_`{|}~]+(?:\.[-a-z0-9!#$%&'*+/=?^_`{|}~]+)*@(?:[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])?\.)*(?:aero|arpa|asia|biz|cat|com|coop|edu|gov|info|int|jobs|mil|mobi|museum|name|net|org|pro|tel|travel|[a-z][a-z])$", RegexOptions.Compiled); private void tokenEdit1_ValidateToken(object sender, TokenEditValidateTokenEventArgs e) { e.IsValid = MailRegex.IsMatch(e.Description); } private void TokenCheckedChanged(object sender, TokenCheckedChangedEventArgs e) { XtraMessageBox.Show(string.Format("{0} {1} Checked: {2}", e.Token.Description, e.Token.Value, e.Token.Checked)); } private void simpleButton2_Click(object sender, EventArgs e) { if (tokenEdit1.CheckedItem != null) tokenEdit1.CheckedItem.Checked = !tokenEdit1.CheckedItem.Checked; } class Test { public object Token { get; set; } } } }

Disclaimer: The information provided on DevExpress.com and affiliated web properties (including the DevExpress Support Center) is provided "as is" without warranty of any kind. Developer Express Inc disclaims all warranties, either express or implied, including the warranties of merchantability and fitness for a particular purpose. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.

Confidential Information: Developer Express Inc does not wish to receive, will not act to procure, nor will it solicit, confidential or proprietary materials and information from you through the DevExpress Support Center or its web properties. Any and all materials or information divulged during chats, email communications, online discussions, Support Center tickets, or made available to Developer Express Inc in any manner will be deemed NOT to be confidential by Developer Express Inc. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.