Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Caret for WPF User Controls

0.00/5 (No votes)
30 Jul 2012 1  
A simple Caret for WPF User Controls

Introduction  

In this article I present a simple Caret which I have successfully used in a couple of my WPF projects. I hope that it can be useful for others too. 

Background 

WPF does not provide a Caret control for User Controls. There is a CaretElement, but it is internal to the framework and undocumented. The presented code can be easily adapted for WinForms as well.

Using the code  

Using the caret is pretty straightforward. You only have to create an instance of the Caret and add it as a child to your user control. In order to move the Caret around, you will have to change its Top and Left properties. You can change Caret's height using the CaretHeight property.

public class MyControl : UserControl 
{ 
    Caret caret = new Caret(); 
    public MyControl() 
    {
        AddChild(caret);
        caret.Top = 100;
        caret.Left = 100;
    }
}

And here is the Caret class:

public class Caret : FrameworkElement
{
    System.Threading.Timer timer;
    Point location;
    public double CaretHeight { get; set; }
    int blinkPeriod = 500;
    Pen pen = new Pen(Brushes.Black, 1);

    public static readonly DependencyProperty VisibleProperty = 
      DependencyProperty.Register("Visible", typeof(bool), 
      typeof(Caret), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.AffectsRender));

    public Caret()
    {
        pen.Freeze();
        CaretHeight = 18; 
        Visible = true;
        timer = new System.Threading.Timer(blinkCaret, null, 0, blinkPeriod);
    }

    protected override void OnRender(DrawingContext dc)
    {
        if (Visible)
        {
            dc.DrawLine(pen, location, new Point(Left, location.Y + CaretHeight));
        }
    }

    bool Visible
    {
        get
        {
            return (bool)GetValue(VisibleProperty);
        }
        set
        {
            SetValue(VisibleProperty, value);
        }
    }

    void blinkCaret(Object state)
    {
        Dispatcher.Invoke(new Action(delegate { Visible = !Visible; }));
    }
            
    public double Left
    {
        get { return location.X; }
        set
        {
            if (location.X != value)
            {
                location.X = Math.Floor(value) + .5; //to avoid WPF antialiasing
                if (Visible)
                {
                    Visible = false;
                }
            }
        }
    }

    public double Top
    {
        get { return location.Y; }
        set
        {
            if (location.Y != value)
            {
                location.Y = Math.Floor(value) + .5; //to avoid WPF antialiasing
                if (Visible)
                {
                    Visible = false;
                }
            }
        }
    }
}

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here