Получить строку в датагрид

Я пытался получить строку, как это:

DataGridRow row = (DataGridRow)dataGrid.ItemContainerGenerator.ContainerFromIndex(i);
TextBlock cellContent = dataGrid.Columns[0].GetCellContent(row) as TextBlock;

Но я только получил null, Есть ли другое решение? Что я делаю неправильно?

Я хочу получить данные из моих клеток. Мои клетки - это флажки.

4 ответа

Это зависит от того, как / когда вы пытаетесь получить эти данные. WPF больше ориентирован на доступ к данным с помощью объектов, связанных в ItemsSource. Итак, если ваш ItemsSource является списком MyObject, то конкретная строка будет иметь тип MyObject вместо чистого DataRow.

Если вы получаете доступ к данным посредством нажатия на них, вы можете сделать что-то вроде этого:

var currentItem = myDataGrid.SelectedItem as MyObject;

Теперь у вас есть текущий MyObject в его первоначальной форме, а не в сетке.

Получение доступа к подходящему объекту данных для манипуляции:

Поскольку a работает с принципалом, который привязан к объекту данных, вы захотите отслеживать свои данные в чем-то вроде файла.

Например, инициализируйте поле для вашего класса MainWindow типа DataTable и назовите его как-нибудь подходящим:

      public partial class MainWindow : Window
{
    private DataTable _cars = new DataTable("Cars");

Затем в вашем конструкторе, после инициализации компонента Window, свяжите DataGrid.ItemSource в коллекцию DataTable как представление данных:

          public MainWindow()
    {
        InitializeComponent();

        dgCars.ItemsSource = _cars.AsDataView();
    }

Теперь каждый раз, когда вы программно добавляете новые строки в таблицу, они будут отражаться внутри, yay! Однако вы хотите иметь возможность работать с данными из пользовательского интерфейса, так что давайте углубимся!

Работа с данными внутри, используя входные данные из пользовательского интерфейса:

Если вы хотите работать с данными, вы можете получить то, что выбрано из элементов внутри, и использовать предоставленные ими индексы, чтобы удалить элементы из, а затем повторно применить DataView. Это резюме, но я остановлюсь на деталях и завершу пример:

  1. Нам нужно перебрать каждый элемент и проверить, выбран ли он перед выполнением нашей логики:

                for (int i = 0; i < dgCars.Items.Count; i++)
        {
            if (dgCars.SelectedItems.Contains(dgCars.Items[i]))
            {
                // This is where we do the magic
            }
        }
    
  2. ОДНАКО, мы не можем удалить элементы из того, что в настоящее время используется для предоставления, иначе мы столкнемся с ошибками IndexOutOfBounds (и, возможно, Enumeration), поэтому для безопасности мы будем использовать копию таблицы для работы:

                DataTable result = _cars.Copy(); //New in this step
        for (int i = 0; i < dgCars.Items.Count; i++)
        {
            if (dgCars.SelectedItems.Contains(dgCars.Items[i]))
            {
                result.Rows.RemoveAt(i); //New in this step
            }
        }
    
  3. Опять же, мы столкнемся с ошибками IndexOutOfBounds, потому что мы перебираем данные, как если бы X количество данных, но каждый раз, когда мы RemoveAt (i), мы перебираем X--количество данных. Итак, добавим счет и будем отслеживать:

                int removed = 0; //New in this step
        DataTable result = _cars.Copy();
        for (int i = 0; i < dgCars.Items.Count; i++)
        {
            if (dgCars.SelectedItems.Contains(dgCars.Items[i]))
            {
                //Subtracting `removed` new in this step
                result.Rows.RemoveAt(i - removed);
    
                removed++; //New in this step
            }
        }
    
  4. И последнее, но не менее важное: мы укажем нашу переменную на наш объект DataTable в куче, а затем переназначим его для обновления нашего DataGrid (более сложное объяснение этого в самом низу моего ответа, если интересно) :

                int removed = 0;
        DataTable result = _cars.Copy();
        for (int i = 0; i < dgCars.Items.Count; i++)
        {
            if (dgCars.SelectedItems.Contains(dgCars.Items[i]))
            {
                result.Rows.RemoveAt(i - removed);
                removed++;
            }
        }
        _cars = result; //New in this step
        dgCars.ItemSource = _cars.AsDataView(); //New in this step
    

Готовый продукт:

Этот пример, который мы создали здесь, позволяет вам удалять данные из, выбирая строки на нем с помощью мыши, а затем нажимая кнопку, которая Clickзначение равно. Простые модификации и изменение логики позволят вам делать то же самое для добавления, редактирования и т. Д. Данных, но с принципом, с которого мы изначально начали, а именно: работать с объектом данных (в данном случае a) и сделать этот элемент ItemsSource для DataGrid.

      public partial class MainWindow : Window
{
    private DataTable _cars = new DataTable("Cars");

    public MainWindow()
    {
        InitializeComponent();

        // THIS WASN'T IN THE BUILD EXAMPLE, BUT AS A BONUS:
        // We could ALSO use this opportunity to setup static
        // column headers if we know what they are in advance!
        _cars.Columns.Add("Year");
        _cars.Columns.Add("Make");
        _cars.Columns.Add("Model");

        dgCars.ItemsSource = _cars.AsDataView();
    }

    private btnRemove_Click(object sender, RoutedEventArgs e)
    {
        int removed = 0;
        DataTable result = _cars.Copy();
        for (int i = 0; i < dgCars.Items.Count; i++)
        {
            if (dgCars.SelectedItems.Contains(dgCars.Items[i]))
            {
                result.Rows.RemoveAt(i - removed);
                removed++;
            }
        }
        _cars = result;
        dgCars.ItemSource = _cars.AsDataView();
    }
}

-Дополнительное чтение-

Ранее на шаге 4 я упоминал:

И последнее, но не менее важное: мы укажем нашу переменную на наш объект DataTable в куче, а затем переназначим dgCars.ItemSource = _cars.AsDataView() обновить наш DataGrid

Причина в том, что оба объекта являются экземплярами класса и находятся в куче. Элементы в куче собираются сборщиком мусора (удаляются из памяти), когда на них больше нет ссылки в стеке. Поскольку это поле нашего MainWindow, и продолжает выходить за рамки, когда мы указываем на DataTable resultмы сохраняем ссылку на эту таблицу и отбрасываем ссылку на исходную таблицу. Таким образом, когда btnRemove_Click завершается, переменная result сборщик мусора, старый DataTable ИСПОЛЬЗУЕМЫЕ для указания на сборщик мусора, и _cars теперь ссылается на наш новый объект DataTable, который мы создали.

В этом ответе содержится значительно более подробная информация, и комментарии к нему также стоит прочитать: qaru.site/questions/435 / ...

Может быть, кому-нибудь будет полезно:

Перед добавлением элемента в DataGrid(WPF), если вы хотите получить ненулевой DataGridRow в будущем, чтобы изменить некоторые свойства, такие как Background, вам необходимо создать новый объект DataGridRow, назначить свой класс свойству DataGridRow.Item, а затем добавить его в DataGrid .

Нравится:

      DataGridRow mRow = new DataGridRow();
mRow.Item = YOUR_DATA_CLASS;
_ = datagrid.Items.Add(mRow);
  for(int row =0; row < dg_CountInventory.Rows.Count; row ++) //Loop through each row
    {
        //Provide the Column Index and row as in Loop
        TextBlock b = dg_CountInventory.Columns[1].GetCellContent(dg_CountInventory.Items[row ]) as TextBlock; 
    }

dg_CountInventory - это мое имя сетки. Этот код будет перебирать все записи, представленные в сетке данных и в ячейке / столбце.#

Другие вопросы по тегам