PDA

View Full Version : سوال: استفاده از Collection ها و DataGridView



jaza_sa
پنج شنبه 31 مرداد 1387, 16:12 عصر
سلام
در مثال فایل ضمیمه ، اطلاعات از یک لیست با نام لیست مشتری (Customers) خونده میشه و در یک DataGridView نمایش داده میشه.
برای اینکه نخواید دیتابیس Attach کنید و ... خودم دستی این لیست رو پر کردم و یکسری اطلاعات وارد کردم (کلاس partial class CustomerProvider در فایل BLL\CreateData.cs)
کلاس مشتری (Customer) خصوصیات مربوط به هر مشتریه
کلاس CustomerProvider توابع مربوط به کلاس مشتری را داره مثلا انتخاب همه مشری ها (GetCustomers) و ...

من در این مثال دو DataGridView دارم که یکی از اونها لیست مشریان هست که کاربر میتونه هر مشتری که میخواد رو انتخاب کنه و به DataGridView مقابل انتقال بده
موقع این اضافه کردن ، از یک لیست کمکی بانام customerSelected استفاده کرم
هنگامی که کاربر کلید درج رو بزنه ، اونهایی که انتخاب شده اند در این لیست ذخیره میشود و نهایتا این لیست بعنوان DataSource دراختیار DataGridView دومی قرار میگیره
اما اشکال کار اینکه فقط دفعه اول اینکار با موفقیت انجام میشه و برای اضافه کردن موارد دیگه در دفعات بعدی باید این کد رو بنویسیم :

dgvSelected.DataSource = null;
dgvSelected.DataSource = customerSelected;یعنی اول باید null بشه و بعد اونرو اختصاص بدیم. چطور باید جلوی اینکار رو گرفت ؟

موقع حذف اون آیتمهایی که انتخاب شده اند هم در حلقه 2 تا 2 تا جلو میره و نمیدونم چرا ؟

آخرین سوال هم اینکه : وقتی Checkbox آیتم ها رو میزنیم و بعد دکمه Back میزیم (بازگشت به فرم قبل) و بعد دوباره Next میزنیم ، تمام Checkbox ها میپرند !!!



باتشکر

mehdi.mousavi
جمعه 01 شهریور 1387, 14:50 عصر
سلام
در مثال فایل ضمیمه ، اطلاعات از یک لیست با نام لیست مشتری (Customers) خونده میشه و در یک DataGridView نمایش داده میشه.
برای اینکه نخواید دیتابیس Attach کنید و ... خودم دستی این لیست رو پر کردم و یکسری اطلاعات وارد کردم (کلاس partial class CustomerProvider در فایل BLL\CreateData.cs)
کلاس مشتری (Customer) خصوصیات مربوط به هر مشتریه
کلاس CustomerProvider توابع مربوط به کلاس مشتری را داره مثلا انتخاب همه مشری ها (GetCustomers) و ...

من در این مثال دو DataGridView دارم که یکی از اونها لیست مشریان هست که کاربر میتونه هر مشتری که میخواد رو انتخاب کنه و به DataGridView مقابل انتقال بده
موقع این اضافه کردن ، از یک لیست کمکی بانام customerSelected استفاده کرم
هنگامی که کاربر کلید درج رو بزنه ، اونهایی که انتخاب شده اند در این لیست ذخیره میشود و نهایتا این لیست بعنوان DataSource دراختیار DataGridView دومی قرار میگیره
اما اشکال کار اینکه فقط دفعه اول اینکار با موفقیت انجام میشه و برای اضافه کردن موارد دیگه در دفعات بعدی باید این کد رو بنویسیم :

dgvSelected.DataSource = null;
dgvSelected.DataSource = customerSelected;یعنی اول باید null بشه و بعد اونرو اختصاص بدیم. چطور باید جلوی اینکار رو گرفت ؟

موقع حذف اون آیتمهایی که انتخاب شده اند هم در حلقه 2 تا 2 تا جلو میره و نمیدونم چرا ؟

آخرین سوال هم اینکه : وقتی Checkbox آیتم ها رو میزنیم و بعد دکمه Back میزیم (بازگشت به فرم قبل) و بعد دوباره Next میزنیم ، تمام Checkbox ها میپرند !!!
باتشکر

سلام.
من برنامه رو دیدم.

1. نیازی نیست که شما هر بار DataSource رو Set کنید! وقتی اینکارو یکبار انجام دادید، در واقع دارید Reference به اون List رو به DataSource نسبت میدید، و هر تغییری در List باعث تغییر خودکار DataSource میشه.

2. در نتیجه، جای اینکه اونو null و سپس دوباره Set کنید، کافیه تا جای این دو خط، از فرمان زیر استفاده کنید:


((CurrencyManager)dgvSelected.BindingContext[customerSelected]).Refresh();به این ترتیب، به Grid میفهمونید که وقتش رسیده خودشو Refresh کنه.

بنابراین، یکبار در ctor، باید DataSource رو Assign کنید، و سپس در تابع btnAdd_Click کافیه تا در انتهای کار، فرمان فوق رو بزنید و تمام.

3. C# بر خلاف C/CPP، بهتون این اجازه رو میده که مقادیر متغیرها رو در همون سطح کلاس و بهنگام تعریف، تعیین کنید. در نتیجه، هنگام تعریف کلاس، جای اینکه در ctor مقادیر رو new کنید، میتونید هنگام تعریف اینکارو انجام بدید؛ یعنی:



public partial class ShowCustomer : Form
{
Customer customer = new Customer();
List<Customer> customers = new List<Customer>();
CustomerProvider customerP = new CustomerProvider();
List<Customer> customerSelected = new List<Customer>();

public ShowCustomer()
{
InitializeComponent();

customers = customerP.GetCustomers();
dgvSelect.AutoGenerateColumns = false;
dgvSelect.DataSource = customers;

dgvSelected.DataSource = customerSelected;
}
که باعث خوانا شدن کد میشه.

4. اگر IComparable و متود Equals و Operator های مساوی و نامساوی رو برای کلاس Customer تعریف کنید، دیگه لازم نیست تا هر جا خواستید دنبال یک Customer بگردید، Predicate ها استفاده کنید که این هم باز به خوانایی و مرتب شدن کد کمک بسزایی میکنه.

5. کلاس CustomerProvider به نظر میرسه که باید Singleton باشه، (از روی اسمش میگم).

6. نوشتن چنین کدی کارامد نیست:


if (row.Cells["cSelected"].Value != null && (bool)row.Cells["cSelected"].Value)بجای نوشتن این کد، میتونید تابعی با Prototype زیر تعریف کنید و هر جا خواستید اونو فراخوانی کنید:


private Boolean IsDataRowSelected(DataGridViewRow row)

به این ترتیب منطق تشخیص Select بودن یا نبودن یک row در جای مشخصی Encapsulate میشه. ضمن اینکه شما نباید دو بار پشت سرهم به row.Cells["cSelected"] دسترسی پیدا کنید. یکبار اونو در متغیری نگه دارید، و سپس بار دوم از اون متغیر استفاده کنید:



private Boolean IsDataRowSelected(DataGridViewRow row)
{
Debug.Assert(row != null);

DataGridViewCell cell = row.Cells["cSelected"];
Debug.Assert(cell != null);

return (cell.Value != null && (bool)cell.Value);
}


7. از نظر من، وقتی Item های Select شده از Grid سمت چپی به Grid سمت راستی اضافه میشن، باید اون Item ها از Grid سمت چپ حذف بشن. (این البته سلیقه ای هستش، و من این روش رو ترجیح میدم).

8. فکر میکنم با این توضیحات دیگه برای Implement کردن تابع btnRemove_Click مشکلی نداشته باشید.

موفق باشید.

jaza_sa
جمعه 01 شهریور 1387, 21:16 عصر
4. اگر IComparable و متود Equals و Operator های مساوی و نامساوی رو برای کلاس Customer تعریف کنید، دیگه لازم نیست تا هر جا خواستید دنبال یک Customer بگردید، Predicate ها استفاده کنید که این هم باز به خوانایی و مرتب شدن کد کمک بسزایی میکنه.

5. کلاس CustomerProvider به نظر میرسه که باید Singleton باشه، (از روی اسمش میگم).

خیلی ممنونم

اگر امکان داره یک مقدار بیشتر راجع به نکات بالا توضیح بدید

باتشکر