1

I have a DataGridTextViewColumn that I want to restrict input for. I've already attached handlers for PreviewTextInput and PreviewKeyDown events, but I also need to limit input via a Paste command. How do I handle the Paste command for this text column? My attempt is below:

<DataGridTextColumn Binding="{Binding MyProperty, UpdateSourceTrigger=PropertyChanged}"
                    Width="Auto">
    <DataGridTextColumn.EditingElementStyle>
        <Style TargetType="TextBox">
            <EventSetter Event="PreviewTextInput"
                         Handler="MyProperty_PreviewTextInput"/>
            <!-- Space, backspace, and delete are not available in PreviewTextInput,
                 so we have to capture them in the PreviewKeyDown event -->
            <EventSetter Event="PreviewKeyDown"
                         Handler="MyProperty_PreviewKeyDown"/>
            <!-- I get a compiler error that "The Property Setter 'CommandBindings'
                 cannot be set because it does not have an accessible set accessor" -->
            <Setter Property="CommandBindings">
                <Setter.Value>
                    <CommandBinding Command="Paste"
                                    Executed="MyProperty_PasteExecuted"/>
                </Setter.Value>
            </Setter>
        </Style>
    </DataGridTextColumn.EditingElementStyle>                    
</DataGridTextColumn>

I understand why my attempt doesn't work, I just can't find a solution I'm happy with that does what I want. The only solution I've found so far is this SO post from 2010 (DataGridTextColumn event binding). I'm hoping there's a better solution by now.

Community
  • 1
  • 1
Brandon Dybala
  • 324
  • 2
  • 11
  • You want to limit the number of characters user can enter or you doing some special handling in your event handlers? – Rohit Vats Apr 13 '13 at 20:21
  • I do want to limit the number of characters, but I'm just doing that with the MaxLength property. My question here is more specifically about limiting _what_ characters are allowed (for instance, limit to alphanumeric only). – Brandon Dybala Apr 13 '13 at 20:30
  • I would suggest you to create an `attached property` and use it for masking, so that you can reuse it for other textboxes. Some useful links - http://stackoverflow.com/questions/1103765/how-to-define-textbox-input-restrictions and http://www.codeproject.com/Articles/34228/WPF-Maskable-TextBox-for-Numeric-Values – Rohit Vats Apr 13 '13 at 20:34
  • Thanks for the links, already found them :) Long term, I probably will make a reusable solution, but for the project I'm working on right now, there's only the one field that we need to limit input, so it wasn't worth the time to make a generic solution (yet). – Brandon Dybala Apr 13 '13 at 20:38
  • Check out the posted answer if it resolves your query? – Rohit Vats Apr 13 '13 at 20:55

1 Answers1

2

As evident from the error CommandBindings property doesn't have setter, so you can't set it from Style but you can do it if you declare CommandBindings as an inline element in TextBox.

Internally, xaml calls CommandBindings.Add() on property if you declare it inline in textBox. So, as a workaround you can use DataGridTemplateColumn and provide a CellTemplate and CellEditingTemplate to give it a look of DataGridTextColumn. Small sample of it -

      <DataGrid.Columns>
            <DataGridTemplateColumn>
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding MyProperty}"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
                <DataGridTemplateColumn.CellEditingTemplate>
                    <DataTemplate>
                        <TextBox Text="{Binding MyProperty}"
                                 PreviewTextInput="MyProperty_PreviewTextInput"
                                 PreviewKeyDown="MyProperty_PreviewKeyDown">
                            <TextBox.CommandBindings>
                                <CommandBinding Command="Paste" 
                                    Executed="CommandBinding_Executed"/>
                            </TextBox.CommandBindings>
                        </TextBox>
                    </DataTemplate>
                </DataGridTemplateColumn.CellEditingTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>
Rohit Vats
  • 79,502
  • 12
  • 161
  • 185
  • Ah, right, I forgot about using a DataTemplate instead, thanks. I figured that was the case about calling CommandBindings.Add() with the inline declaration. – Brandon Dybala Apr 13 '13 at 20:57
  • 1
    In the case of your latest edit (where you added my EventSetters), couldn't you just set the events directly on the TextBox in the DataTemplate, rather than using the style? It would be a little less code. – Brandon Dybala Apr 13 '13 at 20:59
  • Yeah right. I just simply copy/paste from your code. Will update.!! – Rohit Vats Apr 13 '13 at 21:00