none
Uppercase on cell DataGrid RRS feed

  • Question

  • Hey people!

    Well, I'm trying to force the entry (and the reading) of a WPF DataGrid to be always UPPERCASE. I have searched through the Internet without a good solution... Everything would be programatically set. So far I have this piece of code:


                return new DataGridTextColumn
                           {
                               Header = new TextBlock { Text = columnHeader, ToolTip = toolTipText },
                               Binding = new Binding(metaField.FullName.Replace('.', '_')),
                               IsReadOnly = isReadOnly,
                               CellStyle = style
                           };

    What am I missing? the uppercase stuff should be set on CellStyle? If so, how could I implement this?

    Thanks in advance!
    Milton
    Tuesday, January 12, 2010 2:29 AM

Answers

  • Ok, this DOES work... it's not perfect, but it does explain a few things, and its likely you users won't even notice the slight glitchiness. There's some strange async behaviour cranking in there. CharacterCasing doesn't apply to whats already in the TextBox, the KeyUp, GotFocus, Loaded event all occur too quickly (ie, before .Text is populated) so.. a 1 millisecond delay is required for the DataGrid's async methods to finish. That's just a guess btw, but hope this solves your problem.

    XAML

    <my:DataGridTextColumn Binding="{Binding PropertyA}">
        <my:DataGridTextColumn.EditingElementStyle>
            <Style TargetType="TextBox">
                <Setter Property="CharacterCasing" Value="Upper"></Setter>
                <EventSetter Event="TextChanged" Handler="textBox_TextChanged"></EventSetter>                       
            </Style>
        </my:DataGridTextColumn.EditingElementStyle>
    </my:DataGridTextColumn>

    CODE BEHIND

    using System.ComponentModel;
    using System.Threading;

    void textBox_TextChanged(object sender, TextChangedEventArgs e)
    {            
        TextBox textBox = sender as TextBox;            
        BackgroundWorker worker = new BackgroundWorker();
        worker.DoWork += new DoWorkEventHandler(worker_DoWork);
        worker.RunWorkerAsync(textBox);
        worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);            
    }

    void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        TextBox textBox = e.Result as TextBox;
        textBox.Text = textBox.Text.ToUpper();
        textBox.CaretIndex = textBox.Text.Length;
    }

    void worker_DoWork(object sender, DoWorkEventArgs e)
    {            
        Thread.Sleep(1);
        e.Result = e.Argument;
    }

    Warm regards,
    Matt
    • Marked as answer by Milton Abe Wednesday, February 10, 2010 9:45 PM
    Wednesday, February 10, 2010 4:34 AM

All replies

  • I don't think you can do it with CellStyle and even if you could it would only force the entry to uppercase.  You want both entry and reading, so I would use a converter.

    See IValueConverter:

    http://msdn.microsoft.com/en-us/library/system.windows.data.ivalueconverter.aspx


    For entry you will probably need to capture a key event or a text changing event and handle forcing the entry to uppercase at that point.


    John Fenton
    Tuesday, January 12, 2010 3:02 AM
  • the value converter worked but the key event...

    dude, I've no idea how to make this work...

    I've tried a bunch of useless approaches...

    Any other good idea?
    Tuesday, January 12, 2010 8:36 PM
  • How about using an EventSetter in a style that applies to the TextBox using the column's EditingElementStyle?

    Tuesday, January 12, 2010 8:56 PM
  • Would you mind if you wrote a small example or sample?


    Thank you,
    Milton
    Tuesday, January 12, 2010 11:39 PM
  • This should do the trick...

    XAML

    <my:DataGrid AutoGenerateColumns="False" Name="dataGrid1" PreparingCellForEdit="dataGrid1_PreparingCellForEdit">
            <my:DataGrid.Columns>
                <my:DataGridTextColumn Binding="{Binding PropertyA}">
                    <my:DataGridTextColumn.EditingElementStyle>
                        <Style TargetType="TextBox">
                            <Setter Property="CharacterCasing" Value="Upper"></Setter>
                        </Style>
                    </my:DataGridTextColumn.EditingElementStyle>
                </my:DataGridTextColumn>
                <my:DataGridTextColumn Binding="{Binding PropertyB}"></my:DataGridTextColumn>
            </my:DataGrid.Columns>
        </my:DataGrid>

    CODE BEHIND

    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();

            List<TestData> testData = new List<TestData>()
            {
                new TestData(),
                new TestData(),
                new TestData(),
                new TestData(),
            };

            dataGrid1.ItemsSource = testData;
        }   
    }

    public class TestData
    {
        public string PropertyA { get; set; }
        public string PropertyB { get; set; }
    }

    • Marked as answer by Milton Abe Thursday, January 14, 2010 12:38 AM
    • Unmarked as answer by Milton Abe Monday, January 18, 2010 6:40 PM
    • Proposed as answer by Matt Searles Tuesday, February 9, 2010 4:20 AM
    Wednesday, January 13, 2010 6:00 AM
  • Nice that works great!  Combined with the converter he wrote he should have what he needs.

    Very minor edit, he needs to remove this from your code:

    PreparingCellForEdit ="dataGrid1_PreparingCellForEdit"
    John Fenton
    • Marked as answer by Milton Abe Thursday, January 14, 2010 12:38 AM
    • Unmarked as answer by Milton Abe Monday, January 18, 2010 6:40 PM
    Wednesday, January 13, 2010 6:21 PM
  • Yep. Hi 5 *grins*
    • Marked as answer by Milton Abe Thursday, January 14, 2010 12:38 AM
    • Unmarked as answer by Milton Abe Monday, January 18, 2010 6:40 PM
    Wednesday, January 13, 2010 11:26 PM
  • Hello guys... this solution was working great until I found out a weird behavior... Maybe this is a datagrid issue, but let me explaing what's going on:

    The upper case thing will work ONLY IF you double click on the cell, then start editing it. It means that since the cursor starts blinking, then we'll see the upper case thing.

    Now say that you simply click on the cell and try to start editing. We'll see ALWAYS the first character in lower case, then UPPER on the others... Weird huh? Of course this behavior will happen if you have the caps lock OFF...

    I was glad that it had worked... but.. this might be a problem in the future...

    any ideias????

    thank in advance,
    Milton

    • Edited by Milton Abe Monday, January 18, 2010 6:52 PM Found small "bug"
    Thursday, January 14, 2010 12:38 AM
  • Perhaps hook the TextChanged event and check for lowercase letters, then uppercase them if required.
    • Proposed as answer by Matt Searles Tuesday, February 9, 2010 4:19 AM
    • Unproposed as answer by Milton Abe Tuesday, February 9, 2010 2:16 PM
    Monday, February 1, 2010 4:41 AM
  • Didn't work :(
    Tuesday, February 9, 2010 2:17 PM
  • Ok, this DOES work... it's not perfect, but it does explain a few things, and its likely you users won't even notice the slight glitchiness. There's some strange async behaviour cranking in there. CharacterCasing doesn't apply to whats already in the TextBox, the KeyUp, GotFocus, Loaded event all occur too quickly (ie, before .Text is populated) so.. a 1 millisecond delay is required for the DataGrid's async methods to finish. That's just a guess btw, but hope this solves your problem.

    XAML

    <my:DataGridTextColumn Binding="{Binding PropertyA}">
        <my:DataGridTextColumn.EditingElementStyle>
            <Style TargetType="TextBox">
                <Setter Property="CharacterCasing" Value="Upper"></Setter>
                <EventSetter Event="TextChanged" Handler="textBox_TextChanged"></EventSetter>                       
            </Style>
        </my:DataGridTextColumn.EditingElementStyle>
    </my:DataGridTextColumn>

    CODE BEHIND

    using System.ComponentModel;
    using System.Threading;

    void textBox_TextChanged(object sender, TextChangedEventArgs e)
    {            
        TextBox textBox = sender as TextBox;            
        BackgroundWorker worker = new BackgroundWorker();
        worker.DoWork += new DoWorkEventHandler(worker_DoWork);
        worker.RunWorkerAsync(textBox);
        worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);            
    }

    void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        TextBox textBox = e.Result as TextBox;
        textBox.Text = textBox.Text.ToUpper();
        textBox.CaretIndex = textBox.Text.Length;
    }

    void worker_DoWork(object sender, DoWorkEventArgs e)
    {            
        Thread.Sleep(1);
        e.Result = e.Argument;
    }

    Warm regards,
    Matt
    • Marked as answer by Milton Abe Wednesday, February 10, 2010 9:45 PM
    Wednesday, February 10, 2010 4:34 AM
  • Thanks Matt...

    It really DOES work... The sleep trick was awesome... the millisecond really made the difference here.. go figure :)

    Thank you,
    Milton

    Wednesday, February 10, 2010 9:45 PM