I have made a custom usercontrol which consists of a textbox and a canvas which acts like the caret.
The XAML code for the control looks like:
<UserControl x:Class="MadminToolbox.MInputbox" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable="d" d:DesignHeight="250" d:DesignWidth="800"><Grid><TextBox x:Name="Minput" HorizontalAlignment="Left" Height="16" VerticalAlignment="Top" VerticalContentAlignment="Center" Focusable="True" Width="800" BorderBrush="White" BorderThickness="0,0,0,1" FontFamily="Courier New" FontSize="16" CaretBrush="Transparent" IsTabStop="True" IsEnabled="True"><TextBox.Style><Style TargetType="{x:Type TextBox}"><Style.Triggers><Trigger Property="IsFocused" Value="True"><Setter Property="Background" Value="White" /><Setter Property="Foreground" Value="Red" /></Trigger><Trigger Property="IsFocused" Value="False"><Setter Property="Background" Value="Transparent" /><Setter Property="Foreground" Value="White" /></Trigger></Style.Triggers><EventSetter Event="TextChanged" Handler="MyTextbox_previewKeyDown"/></Style></TextBox.Style></TextBox><Canvas Focusable="False"><Border x:Name="Caret" Visibility="Collapsed" Canvas.Left="0" Canvas.Top="0" Width="10" Height="16" Background="BlueViolet" Opacity="0.7" Focusable="False"></Border></Canvas></Grid></UserControl>
The code behind is as follows:
using System.ComponentModel; using System.Windows; using System.Windows.Controls; using System.Windows.Input; namespace MadminToolbox { /// <summary> /// Interaction logic for MInputbox.xaml. /// </summary> [ProvideToolboxControl("MadminToolbox.MInputbox", true)] public partial class MInputbox : System.Windows.Controls.UserControl { public MInputbox() { InitializeComponent(); Carretchanged(); Minput.SelectionChanged += (sender, e) => MoveCustomCaret(); Minput.LostFocus += (sender, e) => Caret.Visibility = Visibility.Collapsed; Minput.GotFocus += (sender, e) => Caret.Visibility = Visibility.Visible; } [Description("Maximaal aantal karakters in het tekstveld"), Category("Common")] public int MaxLength { get { return Minput.MaxLength; } set { Minput.MaxLength = value; } } [Description("Achtergrondkleur"), Category("Common")] public System.Windows.Media.Brush CaretBrush { get { return Caret.Background; } set { Caret.Background = value; } } [Description("Kleur van de rand"), Category("Common")] public System.Windows.Media.Brush MBorder { get { return Minput.BorderBrush; } set { Minput.BorderBrush = value; } } public static readonly DependencyProperty TextBoxBackgroundProperty = DependencyProperty.Register("TextBoxBackground", typeof(System.Windows.Media.Brush), typeof(MInputbox), new FrameworkPropertyMetadata(null)); [Description("Kleur van de cursor"), Category("Common")] public System.Windows.Media.Brush MBackground { get { return (System.Windows.Media.Brush)GetValue(TextBoxBackgroundProperty); } set { SetValue(TextBoxBackgroundProperty, "Transparent"); } } [Description("Forceer hoofdletters of kleine letters"), Category("Text")] public System.Windows.Controls.CharacterCasing CharacterCasing { get { return Minput.CharacterCasing; } set { Minput.CharacterCasing = value; } } [Bindable(false), EditorBrowsable(EditorBrowsableState.Never), Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public string Text { get { return Minput.Text; } set { Minput.Text = value; } } public void Keyfocus() { Keyboard.Focus(Minput); } private void MyTextbox_previewKeyDown(object sender, TextChangedEventArgs e) { // Auto-tab when maxlength is reached if (((System.Windows.Controls.TextBox)sender).MaxLength == ((System.Windows.Controls.TextBox)sender).Text.Length) { // move focus var ue = e.OriginalSource as FrameworkElement; e.Handled = true; ue.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next)); } } private void Carretchanged() { if ((Minput.IsFocused == true) && (Minput.CaretIndex < Minput.Text.Length)) { Minput.Select(Minput.CaretIndex, Minput.CaretIndex + 1); } } private void MoveCustomCaret() { var caretLocation = Minput.GetRectFromCharacterIndex(Minput.CaretIndex).Location; if (!double.IsInfinity(caretLocation.X)) { Canvas.SetLeft(Caret, caretLocation.X); } if (!double.IsInfinity(caretLocation.Y)) { Canvas.SetTop(Caret, caretLocation.Y); } } } }
The canvas which acts like caret has exactly the same width as one character in the textbox. If the user uses the left and right arrow to navigate in the textbox, I would like that the character underneath the caret is selected automaticaly so that it can
be overwritten.
Any views on this matter are very welcome.