0

我正在创建一个与Microsoft Dynamic Nav具有相同功能的DataGrid。 这几乎就像一个 Excel 电子表格。

这个想法是您可以开始编辑单元格。完成后有一些步骤:

  1. 单元格的内容根据列表进行验证。
    1.1 如果列表包含给定的字符串(不区分大小写),则 DataGrid 中的内容将替换为列表中的字符串(也就是大小写正确的字符串)。
    1.2 如果列表不包含字符串,它将显示一个具有可能性的新表单,然后使用用户选择的表单替换已经输入到 DataGrid 中的表单。

  2. 如果用户输入了正确的内容或从列表中选择了正确的值,则 DataGrid 将自动使用预设字符串填充某些列

如果我们看一个例子:如果用户在第 1 列中键入 z,那么我希望第 2 列变为“x”并且焦点移到第 3 列

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)

这里我遇到了一些问题:

  1. 我使用该CellEditEnding事件来验证文本输入。如果我找到正确的文本,那么我currentItem在正确的变量处编辑。但现在我需要打电话dataGrid1.Items.Refresh();,而不是在编辑模式下无法完成。

我的代码:

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; }
}

我在这段代码中遇到的问题是:

  1. 调用刷新后,没有选定的单元格。这意味着不使用鼠标选择单元格就无法继续输入数据。

  2. 当我开始输入新项目(也就是空行)并按 Enter 或 Tab 键时,dataGrid1.CancelEnding()将删除新项目,并且该行再次为空。


问题

  • 是否可以在不调用的情况下编辑数据网格的内容(ItemSoure以及显示的内容)Items.Refresh()
  • 如果没有,可以在Items.Refresh()完成后设置单元格焦点。?
  • 或者有更好的方法吗?
4

1 回答 1

0

我可以回答您有关更新网格内容的问题。

通常,没有必要在更改一个属性后刷新整个网格。(如果您的网格中有大量数据,这也是相当浪费的。)如果您的类DataItem实现INotifyPropertyChangedPropertyChanged接口,并且每次其属性之一的值发生更改时触发一个事件,WPF 将更新表自动。

MSDN上的这个页面包含了一个实现这个接口的例子,你可以在这里找到一个更完整的使用这个接口的例子

这应该消除了使用dataGrid1_PreviewKeyDown事件处理程序的需要,从而消除了无法在网格底部添加新行的问题。

您还应该Mode=TwoWayBindings 中添加DataGridTextColumns。否则,当您编辑单元格时,WPF 不会DataItem使用您在网格中输入的值更新相关对象。

在第一列中输入值后,我查看了在第二列上“制表符”的多种方法,但可惜我没有找到任何有效的方法。

于 2011-07-20T13:19:12.193 回答