I'm working on creating a DataGrid with the same functionality as Microsoft Dynamic Nav.
This is almost like a Excel spreadsheet.
The idea is that you can start editing a cell. After you are done there are some steps:
The content of the cell is validated against a list.
1.1 If the list contains the given string (Not case sensitive), then the content in the DataGrid is replaced with the string from the list (aka the one where the case is right).
1.2 If the list doesn't contain the string it will show a new form with possibilities, and then use the one that the user selects to replace the one already typed into the DataGrid.If the user has typed something right or selected a correct value from the list, then the DataGrid will automatic fill some columns with pre-set string
If we look at an example: If the user types z in column 1 then i want column 2 to become "x" and the focus to move to colum3
DataGrid: (Before enter/Tab pressed)
[Column1] [Column2] [Column3] [Column4]
[ "a" ] [ "b" ] [ "c" ] [ "d" ]
[ "z" ] [ ] [ ] [ ]
(focused)
DataGrid: (Afture enter/tab pressed
[Column1] [Column2] [Column3] [Column4]
[ "a" ] [ "b" ] [ "c" ] [ "d" ]
[ "z" ] [ "x" ] [ ] [ ]
(focused)
Here I encounter some problems:
- I use the
CellEditEndingevent to validate the text input. If I find the correct text then I edit thecurrentItemat the correct variable. But now I need to calldataGrid1.Items.Refresh();and than can't be done while in edit mode.
MyCode:
FormTest.xaml
...
<DataGrid.Columns>
<DataGridTextColumn Header="C1"
Binding="{Binding c1,UpdateSourceTrigger=LostFocus}"/>
<DataGridTextColumn Header="C2"
Binding="{Binding c2,UpdateSourceTrigger=LostFocus}"/>
<DataGridTextColumn Header="C3"
Binding="{Binding c3,UpdateSourceTrigger=LostFocus}"/>
<DataGridTextColumn Header="C4"
Binding="{Binding c4,UpdateSourceTrigger=LostFocus}"/>
<DataGridTextColumn Header="C5"
Binding="{Binding c5,UpdateSourceTrigger=LostFocus}"/>
</DataGrid.Columns>
...
FormTest.xaml.cs
public FormTest()
{
InitializeComponent();
loadMockData();
}
private void loadMockData()
{
dataItems = new DataItems();
dataItems.Add(new DataItem() { c1 = "a", c2 = "b", c3 = "c", c4 = "d", c5 = "e" });
dataItems.Add(new DataItem() { c1 = "a", c2 = "b", c3 = "c", c4 = "d", c5 = "e" });
dataItems.Add(new DataItem() { c1 = "a", c2 = "b", c3 = "c", c4 = "d", c5 = "e" });
dataItems.Add(new DataItem() { c1 = "a", c2 = "b", c3 = "c", c4 = "d", c5 = "e" });
dataItems.Add(new DataItem() { c1 = "a", c2 = "b", c3 = "c", c4 = "d", c5 = "e" });
dataGrid1.ItemsSource = dataItems;
}
private void dataGrid1_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
TextBox editElement = e.EditingElement as TextBox;
DataItem di = dataGrid1.CurrentItem as DataItem;
DataGridCellInfo cell = dataGrid1.CurrentCell;
if (e.Column.DisplayIndex == 0)
{
if (editElement.Text == "z")
{
editElement.Text = "Z";
di.c1 = "Z";
di.c2 = "X";
}
}
}
private void dataGrid1_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter || e.Key == Key.Tab)
{
dataGrid1.CommitEdit();
DataItem di = dataGrid1.CurrentItem as DataItem;
dataGrid1.CancelEdit();
dataGrid1.Items.Refresh();
}
}
private class DataItems : List<DataItem> { }
private class DataItem
{
public int recID { get; set; }
public String c1 { get; set; }
public String c2 { get; set; }
public String c3 { get; set; }
public String c4 { get; set; }
public String c5 { get; set; }
}
The problems I encounter in this code are:
After the refresh is called, there is no selected cell. That means it is not possible to continue entering data without using the mouse to select a cell.
When I start typing a new item (aka the empty row), and press enter or tab, the
dataGrid1.CancelEnding()will remove the new item, and the row is empty again.
The Questions
- Is it possible to edit the content of the datagrid (The
ItemSoureand what is displayed) without callingItems.Refresh()? - If not is it possible to set a cell focus after the
Items.Refresh()is done. ? - Or is there a better way of doing this ?