Yoav
Yoav

Reputation: 3386

get text input from wpf window

I'm using a key_up event on my window to append the data typed to a string builder.

<Grid x:Name="grdMain" KeyUp="grdMain_KeyUp">
        <Grid.RowDefinitions>...

    private StringBuilder buffer = new StringBuilder();
    private void Window_KeyUp(object sender, KeyEventArgs e)
    {
        if (e.Key != Key.Enter)
        {
            buffer.Append(e.Key);
        }

the thing is that the data applied to the buffer is "NumPad4" instead of "4" and "D3" instead of "3"... am i missing something? is there a way to append the data as if it was typed into a textbox? i know that i can convert the data my self but it seems weird that there is no built in way to do so.

Upvotes: 3

Views: 2191

Answers (2)

LPL
LPL

Reputation: 17063

You could use TextCompositionManager.TextInput Attached Event.

<Grid x:Name="grdMain"
      TextCompositionManager.TextInput="grid_TextInput">

In TextCompositionEventArgs you will find what you want.

private void grid_TextInput(object sender, TextCompositionEventArgs e)
{
    MessageBox.Show(e.Text);
}

Upvotes: 2

EvAlex
EvAlex

Reputation: 2938

Ok, this may seem weird at first glance, but I believe that it's the right way to do that. I derived from a TextBox and added ContentPresenter there to host any content and the Content property to set that content.

So, create WPF Custom Control (it's Visual Studio template) called TextBoxContainer. add the following property to it:

    #region Content (DependencyProperty)

    /// <summary>
    /// Gets or sets Content property
    /// </summary>
    public object Content
    {
        get { return (object)GetValue(ContentProperty); }
        set { SetValue(ContentProperty, value); }
    }
    public static readonly DependencyProperty ContentProperty =
        DependencyProperty.Register("Content", typeof(object), typeof(TextBoxContainer),
          new PropertyMetadata(null));

    #endregion

Replace it's style in Assets/generic.xaml file with the following:

<LinearGradientBrush x:Key="TextBoxBorder" EndPoint="0,20" MappingMode="Absolute" StartPoint="0,0">
    <GradientStop Color="#ABADB3" Offset="0.05"/>
    <GradientStop Color="#E2E3EA" Offset="0.07"/>
    <GradientStop Color="#E3E9EF" Offset="1"/>
</LinearGradientBrush>
<Style TargetType="{x:Type local:TextBoxContainer}">
    <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
    <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
    <Setter Property="BorderBrush" Value="{StaticResource TextBoxBorder}"/>
    <Setter Property="BorderThickness" Value="1"/>
    <Setter Property="Padding" Value="1"/>
    <Setter Property="AllowDrop" Value="true"/>
    <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
    <Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst"/>
    <Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:TextBoxContainer}">
                <Grid>
                    <Microsoft_Windows_Themes:ListBoxChrome x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" RenderMouseOver="{TemplateBinding IsMouseOver}" RenderFocused="{TemplateBinding IsKeyboardFocusWithin}" SnapsToDevicePixels="true">
                        <ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                    </Microsoft_Windows_Themes:ListBoxChrome>
                    <ContentPresenter Content="{TemplateBinding Content}"/>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsEnabled" Value="false">
                        <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
                        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

And use it like following:

<local:TextBoxContainer TextChanged="TextBoxGrid_TextChanged" >
    <local:TextBoxContainer.Content>
        <Grid>
            <!-- Any markup here -->
        </Grid>
    </local:TextBoxContainer.Content>
</local:TextBoxContainer>

Note that at any time it has text that contains all text that was input. The only thing that you should be aware of is that some elements prevent some events from bubbling up. For example TextBox stops KeyDown event bubbling. So if you place TextBox inside TextBoxContainer and user will click on it and start to input text there - TextBoxContainer will not receive that text, although it will fire TextChanged event.

Upvotes: 0

Related Questions