Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Tag control like stackoverflow's

Is anyone aware of a Winforms control for c# similar to the Tags control that stackoverflow uses (see below)? tag control example

If not, what are some good alternatives you've used to handle tags?

like image 816
Anders Avatar asked Jun 14 '11 22:06

Anders


2 Answers

I came across your question not long ago looking for the same thing. The closest I could find was a CodeProject article on tag clouds so eventually I gave up on finding something ready out-of-the-box and made one myself. I've made a Nuget package out of it and the source is freely available on GitHub.

Source (GitHub): https://github.com/nathanchere/FerretLib.WinForms

Binary (Nuget): https://www.nuget.org/packages/FerretLib.WinForms

PS: I don't think this should be considered 'spam' since it was specifically written to address the same need as presented in this question.

like image 175
nathanchere Avatar answered Nov 10 '22 22:11

nathanchere


Well after just a couple of minutes playing around, I have an extremely simple implementation. There's a lot more work to go into this but you can see the basic premise behind one way of accomplishing what you're after.

Form1.cs:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace TagInput
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void TagInputContainer_Click(object sender, EventArgs e)
        {
            TextBox box = new TextBox()
            {
                Width = 100,
                Height = 30,
                Font = new Font("Segoe UI Light", 12),
                BorderStyle = BorderStyle.None,
                BackColor = Color.Khaki,
                Location = new Point(0,0),
                Dock = DockStyle.Left,
                Margin = new Padding(2, 0, 0, 0)
            };

            TagInputContainer.Controls.Add(box);
        }
    }
}

Form1.Designer.cs:

namespace TagInput
{
    partial class Form1
    {
        /// <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 Windows Form 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()
        {
            this.TagInputContainer = new System.Windows.Forms.Panel();
            this.SuspendLayout();
            // 
            // TagInputContainer
            // 
            this.TagInputContainer.Cursor = System.Windows.Forms.Cursors.IBeam;
            this.TagInputContainer.Location = new System.Drawing.Point(157, 161);
            this.TagInputContainer.Name = "TagInputContainer";
            this.TagInputContainer.Size = new System.Drawing.Size(406, 30);
            this.TagInputContainer.TabIndex = 0;
            this.TagInputContainer.Click += new System.EventHandler(this.TagInputContainer_Click);
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(664, 395);
            this.Controls.Add(this.TagInputContainer);
            this.Name = "Form1";
            this.Text = "Form1";
            this.ResumeLayout(false);

        }

        #endregion

        private System.Windows.Forms.Panel TagInputContainer;
    }
}

How it works:

Place a Panel on the Form, call it TagInputContainer (it will hold all the "tags"). Set the Cursor property of the Panel to IBeam so the user knows they can type in it. When the user clicks in the TagInputContainer, create a "tag" (TextBox), set its DockStyle property to Left so that they always go to the left and so you don't have to manually handle Location foreach new "tag".

What you can do to improve it:

  • Measure the Font string so that the TextBox width grows and shrinks with the text.
  • Implement the backspace feature where if you press backspace up to the last tag, it will then enable editing of the tag and backspace until you stop.
  • Draw an "x" on the TextBox controls or beside them so the user can click to delete them
  • Handle the space bar button so that when the user presses Spacebar it will create a new tag.

  • Another thing you could do is when the user creates a new tag, set the previous tag to Enabled = false so that it appears as though a real tag has just been created. For this effect I believe it would look better if you did not have the default system 3d box effect on the textboxes, but choose a more flat appearance, such as BorderStyle.FixedSingle or BorderStyle.None.

like image 7
uSeRnAmEhAhAhAhAhA Avatar answered Nov 10 '22 22:11

uSeRnAmEhAhAhAhAhA