Функциональность WPF DataGrid Navision - PullRequest
0 голосов
/ 19 июля 2011

Я работаю над созданием DataGrid с той же функциональностью, что и Microsoft Dynamic Nav .
Это почти как электронная таблица Excel.

Идея состоит в том, что вы можете начать редактирование ячейки. После того, как вы закончите, есть несколько шагов:

  1. Содержимое ячейки проверяется по списку.
    1.1 Если список содержит заданную строку (без учета регистра), то содержимое в DataGrid заменяется строкой из списка (то есть, где регистр прав).
    1.2 Если список не содержит строку, он покажет новую форму с возможностями, а затем использует ту, которую выберет пользователь, для замены уже введенной в DataGrid.

  2. Если пользователь набрал что-то правильно или выбрал правильное значение из списка, DataGrid автоматически заполнит некоторые столбцы предварительно заданной строкой

Если мы посмотрим на пример: если пользователь вводит z в столбце 1, тогда я хочу, чтобы столбец 2 стал «x», а фокус переместился на 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)

Здесь я сталкиваюсь с некоторыми проблемами:

  1. Я использую событие CellEditEnding для проверки ввода текста. Если я найду правильный текст, тогда я отредактирую currentItem в правильной переменной. Но теперь мне нужно позвонить dataGrid1.Items.Refresh();, и это невозможно сделать в режиме редактирования.

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

Проблемы, с которыми я сталкиваюсь в этом коде:

  1. После вызова обновления выбранная ячейка отсутствует. Это означает, что невозможно продолжить ввод данных без использования мыши для выбора ячейки.

  2. Когда я начинаю набирать новый элемент (он же пустая строка) и нажимаю клавишу ввода или табуляцию, dataGrid1.CancelEnding() удалит новый элемент, и строка снова станет пустой.


Вопросы

  • Можно ли редактировать содержимое таблицы данных (ItemSoure и что отображается) без вызова Items.Refresh()?
  • Если нет, можно установить фокус ячейки после выполнения Items.Refresh().
  • Или есть лучший способ сделать это?

1 Ответ

0 голосов
/ 20 июля 2011

Я могу ответить на ваш вопрос об обновлении содержимого сетки.

Обычно нет необходимости обновлять всю сетку после изменения одного свойства.(Это также довольно расточительно, если у вас есть много данных в вашей сетке.) Если ваш класс DataItem реализует интерфейс INotifyPropertyChanged , и вы запускаете событие PropertyChanged каждый раз, когда значение одногоиз-за изменений его свойств WPF автоматически обновит данные в таблице.

Эта страница в MSDN содержит пример реализации этого интерфейса, и вы можете найти более полный пример использованияэтого интерфейса здесь .

Это должно избавить от необходимости использовать обработчик событий dataGrid1_PreviewKeyDown, который, в свою очередь, избавляет от проблемы невозможности добавить новую строкув нижней части сетки.

Вы также должны добавить Mode=TwoWay к Binding с в DataGridTextColumn с.В противном случае, когда вы редактируете ячейку, WPF не обновит соответствующий объект DataItem значениями, которые вы вводите в сетке.

Я рассмотрел несколько подходов к «вкладке» за второйстолбец после ввода значения в первом столбце, но, увы, мне не удалось найти ничего, что сработало.

...