Это моя форма 1 введите описание изображения здесь

Когда я нажимаю на последнюю строку, отображаются данные на втором элементе управления сеткой. Теперь я хочу показать эти данные в следующей форме (форма 2 (форма с покупкой, написанная оранжевым цветом)) datagridview Как я могу это сделать.

enter image description here

        table.Columns.Add("Item Name", Type.GetType("System.String"));
        table.Columns.Add("Main Qty", Type.GetType("System.Decimal"));
        table.Columns.Add("Price", Type.GetType("System.Decimal"));
        table.Columns.Add("Per", Type.GetType("System.String"));
        table.Columns.Add("Basic Amount", Type.GetType("System.Decimal"));
        table.Columns.Add("Dis Amount", Type.GetType("System.Decimal"));
        table.Columns.Add("Dis Percentage", Type.GetType("System.Decimal"));
        table.Columns.Add("Tax Amount", Type.GetType("System.Decimal"));
        table.Columns.Add("Net Value", Type.GetType("System.Decimal"));
        dataGridView1.DataSource = table;

Выше приведена загрузка формы (форма 2)

И ниже RowClick формы 1

 private void gridView1_RowClick(object sender, DevExpress.XtraGrid.Views.Grid.RowClickEventArgs e)
    {

        try
        {
            FRM_Purchase frm = new FRM_Purchase();

            
           
            var ctx = new BizPlusEntities();
            int GettingIdForShowing = (int)gridView1.GetRowCellValue(e.RowHandle, "PurchaseID");
         
            var GettinginToDatabase = ctx.Purchases.Where(x => x.PurchaseID == GettingIdForShowing).ToList();
            foreach (var item in GettinginToDatabase)
            {
                frm.txtPartyName.Text = item.PartyName;
                frm.txtDate.Text = item.Date.ToString();
                frm.txtTerms.Text = item.Terms;
                frm.txtSeries.Text = item.Series;
                frm.txtDueDate.Text = item.DueDate.ToString();
                frm.txtPinvoice.Text = item.Pinvoice.ToString();
                UniqueIdentifier = item.UniquePurchaseNumber;
                string SelectingUniqueIdentfier = ctx.Purchases.SingleOrDefault(x => x.PurchaseID == item.PurchaseID)?.UniquePurchaseNumber ?? "Nulled";

                var GettingInItems = ctx.ItemPurchaseDatas.Where(x => x.UniquePurchaseNumber == SelectingUniqueIdentfier).ToList();
                foreach (var Sam in GettingInItems)
                {
                    TItemName = Sam.ItemName;
                    TMainQty = Sam.MainQty ?? 0;
                    TPrice = Sam.Price ?? 0;
                    TPer = Sam.Per;
                    TBasicAmount = Sam.BasicAmount ?? 0;
                    TDisAmt = Sam.DisAmount ?? 0;
                    TDisP = Sam.DecimalPercentage ?? 0;
                    TTaxAmount = Sam.Gst ?? 0;
                    TTotalAmount = Sam.TotalAmount ?? 0;

                }


                frm.Show();
            }
        }
        catch (Exception)
        {

            throw;
        }
        
    }

Проблема в том, что когда я делаю frm.Table.Rows.Add (TItem, TMainQty ...) на Form1, он показывает, что входной массив длиннее, чем количество столбцов в этой таблице, и когда я создаю новый столбец, он говорит, что столбец уже существует .

0
Indigo Dev 11 Фев 2021 в 11:05

1 ответ

Лучший ответ

Я бы посоветовал отделить ваши данные от способа их отображения. Помимо этого, это упрощает модульное тестирование обработки данных, а также дает лицу, отображающему данные, свободу изменять способ отображения этих данных.

В WPF это разделение модели и представления почти принудительно, в Winforms вам действительно нужно обращать внимание, иначе вы смешиваете обработку данных с тем, как они отображаются, что затрудняет изменение этого.

В вашем случае: должен ли Form1 заботиться о том, как данные отображаются в Form2, должен ли он знать, что Form2 использует DataGridView? Или Form1 должен заботиться только о том, какие данные отображаются в Form2, а не в каком формате?

Правильный интерфейс с Form2 будет заключаться в том, что другие формы сообщают, какие данные должны отображаться, и, если данные могут быть изменены, другая форма может впоследствии запросить значение данных. Что-то вроде этого:

private void ShowForm2()
{
    var dataToShow = this.FetchDataToShow();
    using (var dlg = new Form2())
    {
        dlg.Data = dataToShow;
        var dlgResult = dlg.ShowDialog(this);
        if (dlgResult == DialogResult.OK)
        {
            var dataToProcess = dlg.Data;
            this.ProcessData(dataToProcess);
        }
    }
}

Таким образом, вы только указываете Form2, какие данные отображать, другие формы не заботятся о том, как Form2 отображает свои данные. Это дает Form2 свободу изменять способ отображения данных. У каждого пользователя этой формы будет одинаковый человеческий интерфейс.

Кстати: вы заметили, что я также разделил, откуда Form1 получает данные для Form2 и где хранит результаты? Эта процедура также не заботится о том, как данные отображаются в форме Form1, и дает вам возможность изменять форму Form1 без необходимости изменять эту процедуру.

Использовать привязку данных

Обычно гораздо проще использовать DataBinding для обработки строк в DataGridView, чем для прямого доступа к строкам и ячейкам DataGridView.

Чтобы использовать привязку данных, ваши столбцы должны знать, какое свойство вашего класса должно отображаться в этом столбце. Обычно это делается в Visual Studio Designer.

В вашем случае кажется, что DataGridView в Form2 должен отображать ItemPurchaseDatas: каждая строка в DataGridView будет отображать несколько свойств одного ItemPurchaseData. Используя дизайнер Visual Studio, вы добавите столбцы, и в каждом столбце вы выбираете имя свойства, которое должно отображаться в этом столбце:

DataGridView dataGridView1 = new DataGridView();
DataGridViewColumn columnName = new DataGridViewColumn();
columName.HeaderText = "Item Name";
columName.DataPropertyName = nameof(ItemPurchaseData.Name);
...
DataGridViewColumn columnPrice = new DataGridViewColumn();
columnPrice.HeaderText = "Price";
columnPrice.DataPropertyName = nameof(ItemPurchaseData.Price);
...

Ранее мы видели, что у диалогового окна есть свойство Data, которое содержит данные для отображения. Форме нужен метод для извлечения ItemPurchaseDatas, который должен отображаться в DataGridView:

public IEnumerable<ItemPurchaseData> GetInitialItemPurchaseDatas()
{
    // TODO: use property Data to extract the ItemPurchaseDatas that must be shown
    // in the DataGridView
}

Теперь все, что вам нужно сделать, это обработать событие при загрузке формы, получить данные и поместить их в источник данных dataGridView 1:

private void OnFormLoading(object sender, ...)
{
    List<ItemPurchaseData> itemPurchaseDatas = GetInitialItemPurchaseDatas().ToList();
    this.dataGridView1.DataSource = itemPurchaseDatas;
}

Этого достаточно, чтобы показать данные. Однако он будет доступен только для чтения: любые изменения, которые делает оператор: редактирование, добавление строк, удаление строк и т. Д., Не отражаются в itemPurchaseDatas. Если вы этого хотите, вам понадобится объект, реализующий IBindingList, например BindingList<T>.

Если вы хотите знать изменения, внесенные оператором, обычно имеет смысл добавить следующие методы:

private BindingList<ItemPurchaseData> DisplayedData
{
    get => (BindingList<ItemPurchaseData>)this.dataGridView1.DataSource;
    set => this.dataGridView1.DataSource = value;
}

Теперь каждое изменение, которое оператор вносит в отображаемые данные: добавление / удаление строк, изменение ячеек и т. Д., Отражается в свойстве DisplayedData. Опять же, отображение данных отделено от самих данных: если оператор изменяет внешний вид отображения данных, сортировка строк, перестановка столбцов не влияет на DisplayedData.

Если вам регулярно приходится обрабатывать SelectedRows, подумайте о добавлении следующих свойств:

private ItemPurchaseData CurrentItemPurchaseData =>
    (ItemPurchaseData)this.dataGridView1.CurrentRow?.DataBoundItem;

private IEnumerable<ItemPurchaseData> SelectedItemPurchaseData => 
    this.dataGridView1.DataSource.SelectedRows.Cast<DataGridViewRow>()
        .Select(row => row.DataBoundItem)
        .Cast<ItemPurchaseData>();
    

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

private void OnFormLoading(object sender, ...)
{
    IEnumerable<ItemPurchaseData> itemPurchaseDatas = GetInitialItemPurchaseDatas();
    this.DisplayedData = new BindingList<ItemPurchaseData>(itemPurchaseDatas.ToList());
}

private void OnButtonOk_Clicked(object sender, ...)
{
    ICollection<ItemPurchaseData> editedData = this.DisplayedData;
    // if needed: check which items are changed
    this.ProcessChangedData(editedData);
}

Опять же: из-за разделения представления и модели код в представлении является однострочным.

Если вы хотите только отобразить данные, это

0
Harald Coppoolse 19 Фев 2021 в 14:14