Basic DataGridView questions - c#

I have a datagridvew with a bindinglist whose datasource is to an intersection table. I have an another bindinglist which acts as a lookup and is bound to one of the columns that is a DataGridViewComboBoxColumn type. I have simplified the binding lists as shown below:
public IList<Flight> flights = new List<Flight>()
{
new Flight { DepartureID = 1, DestinationID = 1, FlightNumber = "101" },
new Flight { DepartureID = 2, DestinationID = 2, FlightNumber = "202" },
new Flight { DepartureID = 3}
};
public IList<Departure> departures = new List<Departure>()
{
new Departure {ID = 1, City = "Toronto"},
new Departure {ID = 2, City = "Chicago"},
new Departure {ID = 3, City = "New York"}
};
public IList<Destination> destinations = new List<Destination>()
{
new Destination {ID = 1, City = "London"},
new Destination {ID = 2, City = "Paris"},
new Destination {ID = 3, City = "Amsterdam"}
};
I have five columns in my datagridview:
Depature ID: Textbox
Departure: Textbox
Destination ID: Textbox
Destination: Combobox
Flight Number: Textbox
I have three questions:
1) The departures are readonly. I would like to display the ID and the city. How can I add textbox to automatically look up the City value. I thought of the OnCellPainting event and looking it up but the e.Value is readonly. Is there some OnCellDrawing event similar to Delphi.
2) On the combobox for Destinations, once an user selects a value from the combobox, how do I also update the Destination ID also?
3) How do I handle the scenario where I only have values for Departure (e.g. this record (new Flight { DepartureID = 3}) throws an invalid value error because there's no value for the combobox to lookup)

1) The easiest way to set your Departure city would be using a ComboBox like the destination. Binding it to the list of Destinations and marking this column as ReadOnly. This would handle the Departure with no code.
2) You should bind your DataGridView and your List of flights with a BindingSource. Because your ComboBox ValueMember is your ID and your DisplayMember is the name of the city, it will automatically update your ID.
3) If you want to bind your data, the template should be the same. You should always have a destination and flight number in your list. If they don't have value, set them to null. You're gonna be able to handle the null value while you can't handle a non-existent attribute.
new Flight { DepartureID = 3, DestinationID = null, FlightNumber = null }

Related

How to set multiple values of properties inside an object in C#?

Please tell me how to add multiple properties inside an single object.
like- if there is a class having 5 variables defined with get and set.
I want to add like 2 values for each variable through a single object of that class like
class Info{
int count{get , set,};
string name{get , set,};
string Dept {get , set,};
string Address {get , set,};
long contact {get , set,};
info obj =new Info();
/* Now after this I want to take 2 rows like
in first row I want to set it's values through a single object
Count=1,name="Robert",Dept="Computer",Address="India",Contact=434343
in row 2nd row
Count=1,name="Robbin",Dept="Electronic",Address="Colombo",Contact=54545
*/
}
/// Now please explain me how to set like above two rows values inside one object.. ///
I think what you're looking for is inline object initialization: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/how-to-initialize-objects-by-using-an-object-initializer
You can write it on a single line but the code would look better if you break it into multiple lines:
Info infoObj = new Info
{
Count = 1,
Name = "Robert",
Dept = "Computer",
Address = "India",
Contact = 434343
};
If what you mean is initializing a class with set properties, look at Peter Sandor's answer.
if you're looking to declare a class with a set of fields that'll be filled with values upon initialization without giving them values (aka. default values), then this might help:
class Info
{
public int count = 5;
pubic string name = "Robert"
}
Please note that these are fields and not properties though, if you'd like to do the same with properties instead of fields, i'd suggest doing this with propfull:
private int count = 5;
public int Count
{
get { return count; }
set { count = value; }
}
Hope this helps!
Instead of creating an instance of the Info class, make a List of Info:
List<Info> aSingleObj = new List<Info>();
Now you can add as many things to the single object:
aSingleObj.add(new Info { Count = 1, name = "Robert", Dept = "Computer", Address = "India", contact = "434343" });
aSingleObj.add(new Info { Count = 1, name = "Robbin", Dept = "Electronic", Address = "Colombo", contact = "54545" });
To distinguish between them, and print the output, do:
Console.WriteLine($"First row: Count = {aSingleObj[0].Count}, Name = {aSingleObj[0].name}, Department: {aSingleObj[0].Dept}, Address = {aSingleObj[0].Address}, Contact = {aSingleObj[0].contact}");
and for second row:
Console.WriteLine($"Second row: Count = {aSingleObj[1].Count}, Name = {aSingleObj[1].name}, Department: {aSingleObj[1].Dept}, Address = {aSingleObj[1].Address}, Contact = {aSingleObj[1].contact}");

Setting the orderLine property on an item when updating an invoice

My problem is that after creating an invoice, I can never get new line items to reference their corresponding sales order line item.
I have been generating invoices via SuiteTalk. When I initially create an invoice, I empty the lineItemList and add back in the items I need. I make sure the orderLine property matches the sales order line item line number. This works great.
But when I try and update the invoice with additional line items, I can never get the new items to retain their orderLine property. The orderLine property is used for the "Invoiced" column on the Sales Order.
In order to get the referencing to be correct, I need to delete the invoice and create it again with all of the line items I need.
Does anyone know if what I am trying to do is possible?
In this example, I use this CreateInvoice function to create the invoice from scratch and add it to NetSuite. Everything works as expected.
public void CreateInvoice(SalesOrder salesOrder) {
Invoice brandNewInvoice = new Invoice() {
createdFrom = new RecordRef() {
internalId = salesOrder.internalId,
},
entity = salesOrder.entity,
tranDate = endDate,
tranDateSpecified = true,
startDate = startDate,
startDateSpecified = true,
endDate = endDate,
endDateSpecified = true,
itemList = new InvoiceItemList(),
};
invoice.itemList.item = GetInvoiceItemList(salesOrder); //see the function shown further down
netSuiteService.add(brandNewInvoice);
}
In this example, the invoice is already created and so I get it from NetSuite and then replace the existing itemList with a new one. After the update, the invoice will now have NO orderLine property for any of the line items. The invoice also loses its "Created From" field because there are no line items with the orderLine property set.
public void UpdateInvoice(SalesOrder salesOrder, String invoiceInternalId) {
Invoice invoice = GetNetSuiteInvoice(invoiceInternalId);
invoice.itemList.item = GetInvoiceItemList(salesOrder); //see the function shown further down
netSuiteService.update(invoice);
}
this is the function used to create the itemList:
public InvoiceItem[] GetInvoiceItemList(SalesOrder salesOrder) {
InvoiceItem[] invoiceItemList = new InvoiceItem[salesOrder.itemList.item.Length];
for (int i = 0; i < salesOrder.itemList.item.Length; i++) {
SalesOrderItem soItem = salesOrder.itemList.item[i];
double quantity = 1;
invoiceItemList[i] = new InvoiceItem() {
item = new RecordRef() {
internalId = soItem.item.internalId,
name = soItem.item.name,
},
amount = quantity * Double.Parse(soItem.rate),
amountSpecified = true,
quantity = quantity,
quantitySpecified = true,
price = new RecordRef() {
internalId = soItem.price.internalId,
name = soItem.price.name,
},
rate = soItem.rate,
orderLine = soItem.line, //this will establish the link between the invoice and the sales order
orderLineSpecified = true,
taxRate1 = soItem.taxRate1,
taxRate1Specified = true,
};
}
return invoiceItemList;
}
Actually what you are looking for is the intialize operation. You need to use initialize in order for Netsuite to properly fill in the created from and orderline props. From the NS Help there is a C# example of creating a Cash Sale:
private void Initialize()
{
this.login(true);
InitializeRef ref1 = new InitializeRef();
ref1.type = InitializeRefType.salesOrder;
//internal id of the sales order to be converted to cash sale
ref1.internalId = "792";
ref1.typeSpecified = true;
InitializeRecord rec = new InitializeRecord();
rec.type = InitializeType.cashSale;
rec.reference = ref1;
ReadResponse read1 = _service.initialize(rec);
}
This is normal, when transforming a transaction to another transaction (e.g. SO to Inv, PO to IR). When you transform, most of the information from the source transaction will be carried over. Like what you are doing which is creating an Invoice from Sales Order(Base on your code below).
createdFrom = new RecordRef() {
internalId = salesOrder.internalId,
},
You don't need to get the line item information from the Sales Order and put it in the Invoice because it will be pre-populated once you create it form Sales Oder(unless you need to change a value of a line item column).
One behavior of a transformed record(Invoice in your case), if you remove a line item from the Invoice you will lose the link to the Sales order(orderLine) and if you remove all the line item you will totally lose the link between the two transactions (createdfrom). This is what you are experiencing. orderLine/createdFrom is a field populated by the system, it looks like you are populating it but you are not.

DevExpress LookupEdit issue

My DevExpress.XtraEditors.LookUpEdit control is not working
I Fill the combo with this code:
void FillCombo()
{
cboStep.Properties.DataSource = ProceduresDALC.Fill_StepDetail(" Where StepID = "+_StepID);
cboStep.Properties.DisplayMember = "Description";
cboStep.Properties.ValueMember = "StepID";
cboStep.Properties.Columns.Clear();
cboStep.Properties.Columns.Add(new DevExpress.XtraEditors.Controls.LookUpColumnInfo("Description", "Step Detail"));
}
The values are loaded into LookUpEdit
But when I choose a value from the LookUpEdit it gives me the first value only instead of my preferred value.
Just make sure that StepID is a primary key here. If it isnt a primary key then it will give you the first value on change index event
Your code works correctly to me with my datasource:
void FillLookUp() {
lookUpEdit1.Properties.DataSource = new List<StepDetails>{
new StepDetails(){ StepID = 0, Description = "Step1" },
new StepDetails(){ StepID = 1, Description = "Step2" },
new StepDetails(){ StepID = 2, Description = "Step3" },
};
lookUpEdit1.Properties.DisplayMember = "Description";
lookUpEdit1.Properties.ValueMember = "StepID";
lookUpEdit1.Properties.Columns.Clear();
lookUpEdit1.Properties.Columns.Add(new LookUpColumnInfo("Description", "Step Detail"));
}
It seems that some problems with retrieving data from your database cause this issue.
So, I suggest you contact the DevExpress Support for further research.

Get value from combobox

I have 2 tables in the database carrier and vendor. vendor has a foreign key of Carrier_Id. When the user want add a vendor, the user will select a carrier from a combobox where the valve from carrier table.
The problem I facing now is that,I don't know how to get the valve from combobox so that I can insert it into the database.
I use this code to get valve from carrier table to show in the combobox.
MyinvoiceDataDataContext contect = new MyinvoiceDataDataContext();
var st = from s in contect.Carriers
select new { s.CarrierID, s.CarrierName};
comVendorCarrier.ItemsSource = st;
comVendorCarrier.DisplayMemberPath = "CarrierName";
comVendorCarrier.SelectedValuePath = "CarrierID";
To get the value of this combobox (i.e. the selected carrier), all you need is just use the two properties SelectedValue to get the CarrierId or SelectedText to get the value (i.e. CarrierName).
For example, you could get the id of the selected carrier by using:
int SelectedCarrierId = int.parse(comVendorCarrier.SelectedValue.ToString());
Or if you need the CarrierName you should use:
string CarrierName = comVendorCarrier.SelectedText;
Edit: Assuming that your tables have the following structre:
Carrier:
CarrierId.
CarrierName.
Vendor:
VendorId.
CarrierId: a foreign key references Carriers(CarrierId).
VendorName.
These two tables should be mapped in your .dbml file to two entities Vendor and Carrier, in which the Vendor class has a property of type Carrier that represents the foreign key CarrierID.
Then in order to view CarrierName in the vendors list, you can do this:
var vendorsList = _db.Vendors
.Select( vendor => new
{
VendorId = vendor.Id,
VendorName = vendor.Name,
CarrierName = vendor.Carrier.Name
});
using (MyinvoiceDataDataContext connv = new MyinvoiceDataDataContext())
{
Vendor editven = (from s in connv.Vendors
where s.VendorID == vendor.VendorID
select s).FirstOrDefault();
editven.VendorAddress = editven.VendorAddress;
editven.VendorBalance = editven.VendorBalance;
editven.VendorContactName = editven.VendorContactName;
editven.VendorEmail = editven.VendorEmail;
editven.VendorFax = editven.VendorFax;
editven.VendorName = editven.VendorName;
editven.VendorPaymentTerms = editven.VendorPaymentTerms;
editven.VendorPhone = editven.VendorPhone;
editven.VendorRemark = editven.VendorRemark;
editven.VendorTax = editven.VendorTax;
editven.VendorWebsite = editven.VendorWebsite;
editven.CarrierID = editven.CarrierID;
connv.SubmitChanges();
}

GridView DataKeyNames of nested collections or custom object

I'm using custom objects to bind to a GridView.
Suppose I have a collection of Car Companies (Audi, Ford, BMW, etc). Each Company object has properties like Id, Name, Country, etc.
Each Company also has a Collection of Cars. Each Car has properties like Id, Model, Year, etc.
I want to bind this info to a GridView.
So I'm retrieving a query of Companies and in first object of each Cars Collection, has data of one car (the object model is like this because in other scenarios I have to list all the cars of a Company).
There is no problem when I bind the Gridview to the Companies collection. I can list each company and each car info I want to show.
The problem arises when I want to set the DataKeyNames. I want to set it with the Id of each Car (not the Id of each company) for comparing cars.
I was trying something like this:
GridViewCompanies.DataSource = companies;
GridViewCompanies.DataKeyNames = new string[] { "Cars[0].Id" };
But it does not work, it says it does not contain a property with the name.
Is there any way to set it?
I don't want to bind the Gridview to a Cars collection instead because if I do it that way, I would miss the info of each Company and I need to use company's properties too.
Many thanks.
Try it:
var carCompanyList = new[]
{
new { Id = 1, Name = "Audi", Cars = new[] { new { Id = 10, Model = "Audi_Model_1" }, new { Id = 12, Model = "Audi_Model_2" } } },
new { Id = 2, Name = "Ford", Cars = new[] { new { Id = 20, Model = "Ford_Model_1" }, new { Id = 22, Model = "Ford_Model_2" } } }
};
var gridViewData = from carCompany in carCompanyList
select new
{
carCompany.Id,
carCompany.Name,
firstModelId = carCompany.Cars == null || carCompany.Cars.Count() == 0 ? 0 : carCompany.Cars.First().Id
};
CarModelGridView.DataSource = gridViewData;
CarModelGridView.DataKeyNames = new [] { "firstModelId" };
CarModelGridView.DataBind();

Categories

Resources