我有一個資料系結資料網格視圖和一些按鈕,用于從 SQL 資料表中編輯、添加、洗掉資料。我的主要目標是制作一個按鈕,用于從用戶選擇的資料表中洗掉 SelectedRows。
由于我只需要來自第一列的資料,因此我的 Column.Index 將始終為 0
現在,從用戶選擇的行中,我將 Row.Index 保存在一個陣列中,這樣我就可以查明并洗掉之后選擇的行所在的行。問題是我不能在 foreach 回圈之外使用我的 SelectedRowIndexes 陣列,因為它是一個區域變數。例如,當我運行 Console.WriteLine 命令時,我收到我的陣列在當前背景關系中不存在的錯誤。我想錯了嗎?有一些解決方法嗎?
private void BtnRemoveClick(object sender, System.EventArgs e)
{
foreach (DataGridViewRow row in datagridview1.SelectedRows)
{
int[] SelectedRowIndexes = { row.Index };
}
for (int i=0; i<SelectedRowIndexes.Length; i )
{
Console.WriteLine(SelectedRowIndexes[i]); // error CS0103: The name 'SelectedRowIndexes' does not exist in the current context
}
}
uj5u.com熱心網友回復:
如果您的網格系結到 a DataTable,則DataBoundItem每行的 a 是DataRowView。您可以使用回圈或 LINQ 查詢SelectedRows將網格中的每一個獲取到陣列或集合中,呼叫Delete每一個,然后呼叫Update資料配接器以保存所有更改。例如
var rows = myDataGridView.SelectedRows
.Cast<DataGridViewRow>()
.Select(dgvr => dgvr.DataBoundItem)
.Cast<DataRowView>()
.ToArray();
foreach (var row in rows)
{
row.Delete();
}
myDataAdapter.Update(myDataTable);
這假定myDataTable系結到myDataGridView并且myDataAdapter已經配置了適當的DeleteCommand.
如果你已經系結了DataTablevia a BindingSource,你應該這樣做,那么你也可以用另一種方式來做:
var rowIndexes = myDataGridView.SelectedRows
.Cast<DataGridViewRow>()
.Select(dgvr => dgvr.Index)
.ToArray();
for (var i = rowIndexes.GetUpperBound(0); i >= 0; i--)
{
var rowIndex = rowIndexes[i];
myBindingSource.RemoveAt(rowIndex);
}
然后,您將使用資料配接器以相同的方式保存更改。
uj5u.com熱心網友回復:
您沒有提到您在 DataGridView 中顯示的專案型別。為了簡化討論,我假設您展示了一系列Products
class Product
{
...
}
將您的表單與資料庫訪問分開
您需要訪問您的資料庫。您的表單不必知道資料的存盤方式和存盤位置。它所需要知道的是,您可以通過某種方式將資料放入其中,然后再將其取回。
這樣做的好處是您可以將表單與資料庫分離。如果您稍后決定更改訪問資料庫的方式,例如您決定使用物體框架而不是 SQL,那么您的表單不必更改。或者,如果您需要以不同的形式訪問資料庫,您可以重用該資料庫。
隱藏如何訪問資料庫的類通常稱為Repository。您可以在其中存盤物品。稍后您可以查詢存盤的專案。
在您的存盤庫中,您至少需要以下方法
Interface IProductRepository
{
IEnumerable<Product> FetchProducts(...); // TODO: invent a suitable name
void DeleteProducts(IEnumerable<Product> productsToDelete);
... // other useful methods
}
FetchProducts將獲取您需要在 DataGridView 中顯示的產品。由于您的存盤庫不知道產品顯示在我無法使用的 DataGridViewFetchProductsToDisplay或類似的東西中。引數必須過濾產品。
class ProductRepository : IProductRepository
{
// TODO: implement
}
實施不是這個問題的一部分。您可以使用物體框架、Dapper 或普通的舊 SQL。您班級的用戶不會知道,也不必知道您如何訪問資料。
訪問 DataGridView 中的產品
您說您已將資料資料系結到 DataGridView。因此,我假設您知道如何實體化 DataGridView、其列等。詳細資訊不在此問題范圍內。
屬性將允許您訪問顯示的產品:
// access all Products in the DataGridView
public BindingList<Product> DisplayedProducts
{
get => (BindingList<Product>) this.DataGridView1.DataSource;
set => this.DataGridView1.DataSource = value;
}
// returns the current Product or null if there is no current Product
Product CurrentProduct => this.DataGridView1.CurrentRow?.DataBoundItem as Product;
// returns the (possible empty) sequence of selected Products
IEnumerable<Product> SelectedProducts => this.DataGridView1.SelectedRows
.Cast<DataGridViewRow>()
.Select(row => row.DataBoundItem)
.Cast<Product>();
換句話說:從 SelectedRows 的序列中,將每一行轉換為 DataGridViewRow。從此 DataGridViewRows 序列中的每一行獲取 DataBoundItem 的值。將每個 DataBoundItem 轉換為 Product。
使用初始產品串列填充 DataGridView:
IProductRepository ProductRepository {get;} // initialized in constructor
void InitializeProductsDataGridView()
{
IEnumerable<Product> productsToDisplay = this.ProductRepository.FetchProductsToDisplay(...);
this.DisplayedProducts = new BindingList<Product>(productsToDisplay.ToList());
}
回到你的問題
我的主要目標是制作一個按鈕,用于從用戶選擇的資料表中洗掉 SelectedRows。
現在您已經正確定義了對 DataGridView 中產品的訪問權限和對資料庫的訪問權限,這是一個兩行方法:
void DeleteSelectedProducts()
{
IEnumerable<Product> selectedProducts = this.SelectedProducts;
this.ProductRepository.DeleteProducts(selectedProducts);
}
概括
不要做一個可以做任何事情的大表格。分開你的顧慮(如果你不知道這個詞,谷歌它)。在這種情況下:將您的表單與對資料庫的訪問分開,并將對 DataGridView 中產品的訪問分開。
這樣做的好處是更容易理解你的類是做什么的。更改它們更容易,而無需更改班級的用戶。測驗這些較小的類更容易,并且更容易重用專案。
我的大多數具有 DataGridView 的表單都具有我在上面定義的訪問屬性。事實上,我創建了通用擴展方法,因此我可以將它們用于每個 DataGridView。我只需要為他們撰寫一次單元測驗。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/509947.html
標籤:C#。网表格前锋范围
