1. The DataGridView control supports the standard Windows Forms data binding model, so it will bind to instances of classes described in the following list:
· Any class that implements the IList interface, including one-dimensional arrays.
· Any class that implements the IListSource interface, such as the DataTable and DataSet classes.
· Any class that implements the IBindingList interface, such as the BindingList<(Of <(T>)>) class.
· Any class that implements the IBindingListView interface, such as the BindingSource class.
IList doesn’t implement any of the interfaces described above, that’s the reason that your DataGridView doesn’t display anything.
Du kan med andra ord inte binda mot ett objekt som är av en interface-typ (IList), utan du måste binda mot ett objekt som är av en implementations-typ (List).
Tyvärr är det inte riktigt så enkelt, i vårt fall har vi en struct som får sina värden från ett gammalt vb-program.
Eftersom structen måste se ut som den gör (vi kan även ha den som en klass) men vi kan inte lägga till några konstruktorer eftersom vi får fel vid inläsningen av data då.
Du måste instantiera en lista och alla rader för att kunna använda den som datasource till tex en datagridview. Eftersom vi inte kan göra det så finns värdena där och vi har som alternativ att antingen krånga med datatables (väldigt omständigt) eller skapa någon slags factory till de klasserna. Jag sitter fortfarande och funderar på vilket som blir enklast att underhålla och förstå. För tillfället så loopar vi igenom allting för att få in det i våra winforms kontroller och det känns riktigt b men jag har inte lyckats få till någon annan lösning än.
Lösningen på min frågeställning postar jag här lite senare!
Du måste instantiera en lista och alla rader för att kunna använda den som datasource till tex en datagridview. Eftersom vi inte kan göra det så finns värdena där och vi har som alternativ att antingen krånga med datatables (väldigt omständigt) eller skapa någon slags factory till de klasserna. Jag sitter fortfarande och funderar på vilket som blir enklast att underhålla och förstå. För tillfället så loopar vi igenom allting för att få in det i våra winforms kontroller och det känns riktigt b men jag har inte lyckats få till någon annan lösning än.
Få se om jag hänger med här...
Du har en lista med structer som inte kan innehålla en konstruktor, men för att binda listan till en datagridview så måste struterna ha en konstruktor annars fungerar det inte, rätt?
Om det är fallet så hade jag helt enkelt skapat mig en "wrapperklass" som hade motsvarat er struct, omvandlat din lista av structer till en lista av wrapperklasser och bundit dessa till datagridviewn. Det enklast sättet att mappa mellan structen och wrapperklassen blir att wrapperklassen innehåller en struct och alla properties i wrapperklassen pekar ner på samma property i structen.
Du har en lista med structer som inte kan innehålla en konstruktor, men för att binda listan till en datagridview så måste struterna ha en konstruktor annars fungerar det inte, rätt?
Om det är fallet så hade jag helt enkelt skapat mig en "wrapperklass" som hade motsvarat er struct, omvandlat din lista av structer till en lista av wrapperklasser och bundit dessa till datagridviewn. Det enklast sättet att mappa mellan structen och wrapperklassen blir att wrapperklassen innehåller en struct och alla properties i wrapperklassen pekar ner på samma property i structen.
- M
Prestandan för detta torde bli önskvärd... Ska genast ge mig på det! Tack för tipset!
Där var jag katig och markerade tråden som löst för jag trodde att jag bergis kunde hitta någon genomgång på nätet men icke!
Några förslag eller länkar till hur man kan göra / tänka för att det ska bli rätt?
Vi kan ta ett enkelt exempel
[StructLayout(LayoutKind.Sequential)]
public struct SimpleStruct
{
public short ID;
public string Description;
public uint Value;
}
Sedan får jag skapa en klass som representerar SimpleStruct
public class SimpleStructWrapper
{
private short id;
private string description;
private uint value;
public SimpleStructWrapper(short _id, string _description, uint _value)
{
id = _id;
description = _description;
value = _value;
}
}
Hur ska jag tänka nu? Jag behöver ju en extern funktion som tar emot min lista med SimpleStruct och omvandlar den till en lista med SimpleStructValue, vad är mest prestanda effektivt nu? Att loopa igenom hela innehållet i listan?
public class InfoHolder
{
private InfoHolderStruct _innerStruct;
public InfoHolder(InfoHolderStruct innerStruct)
{
_innerStruct = innerStruct;
}
public InfoHolder()
{
_innerStruct = new InfoHolderStruct;
public InfoHolderStruct InnerStruct
{
get;
}
public Guid Id
{
get { return _innerStruct.Id; }
set { _innerStruct.Id = value; }
}
public string Name
{
get { return _innerStruct.Name; }
set {_innerStruct.Name = value; }
}
Jag testade att köra 10 000 000 dvs 10 miljoner rader och det tog ca 75 sekunder för min winform att skapa de raderna samt konvertera dem till en användningsbar lista och presentera dem i min datagridview...
Låt oss nu spåna att jag endast vill ha en enda metod för att returnera en bindningsbar lista så vill jag kunna göra ungefär följande
// Method to convert a list of structs to a bindable list
private List<HolderType> GenerateUsableList<HolderType>(List<StructType> structlist)
{
// Create the usable list
List<HolderType> holderlist = new List<HolderType>();
// run through the structlist and add every struct to the holderlist
structlist.ForEach(delegate(StructType structtype)
{
holderlist.Add(new HolderType(structtype));
});
return holderlist;
}
Här saknas någonting jag får upp att StructType saknas när jag vill ha den som parameter kan jag inte använda mig av okända StructTyper som parameter?
Jag testade att köra 10 000 000 dvs 10 miljoner rader och det tog ca 75 sekunder för min winform att skapa de raderna samt konvertera dem till en användningsbar lista och presentera dem i min datagridview...
Av de 75 sekunderna så gick säkert 74.5 sekunder till att binda alla dessa poster till din datagridview!!!
Själva konverteringen är blixtsnabb då du aldrig konverterar något, utan helt enkelt skapar ett nytt objekt och lägger in din strukt där. Om du tänker använda dig av riktigt många objekt (nu kanske 10 miljoner är overkill :) ) men iallafall run 100.000 och dessa tar några byte, så kanske det är bättre med klasser istället för strukter, för JAG TROR att du kommer skapa en ny minesarea i din heap för din strukt i klassen medans om du använt en klass istället så hade du bara fått 2 referenes till samma område i stacken.. men det är säkert någon annan som har bättre koll på vad som händer med strukter när man flyttar runt dem till olika objekt...
Av de 75 sekunderna så gick säkert 74.5 sekunder till att binda alla dessa poster till din datagridview!!!
Själva konverteringen är blixtsnabb då du aldrig konverterar något, utan helt enkelt skapar ett nytt objekt och lägger in din strukt där. Om du tänker använda dig av riktigt många objekt (nu kanske 10 miljoner är overkill :) ) men iallafall run 100.000 och dessa tar några byte, så kanske det är bättre med klasser istället för strukter, för JAG TROR att du kommer skapa en ny minesarea i din heap för din strukt i klassen medans om du använt en klass istället så hade du bara fått 2 referenes till samma område i stacken.. men det är säkert någon annan som har bättre koll på vad som händer med strukter när man flyttar runt dem till olika objekt...
- M
Ska kolla, det blir inte mer än 600*3*3 structer dock...
Gladh skrev:
Du måste skicka med StructType till metoden också annars vet den ju bara av vilken typ din HolderType är.
Nu är jag lite tillbaka på noll då jag givetvis inte kan göra
private List<HolderType> GenerateUsableList<HolderType, StructType>(List<StructType> structlist)
where HolderType : new()
{
// Create the usable list
List<HolderType> holderlist = new List<HolderType>();
// run through the structlist and add every struct to the holderlist
structlist.ForEach(delegate(StructType structtype)
{
[b]holderlist.Add(new HolderType(structtype));[/b]
});
return holderlist;
}
Tänkte det skulle fungera men då får jag felmeddelande på raden i fetstil och meddelandet lyder
Visual Studio 2008 skrev:
'HolderType': cannot provide arguments when creating an instance of a variable type
Så jag försökte lägga till
where HolderType: class, new()
men det hjälper inte heller.
Det jag helst skulle vilja göra är
where: class, HolderType, new()
men då får jag ett meddelande om Circular dependancy. Attans att jag ska in och pilla på sådana här fullständigt onödiga saker.
// Method to convert a list of structs to a bindable list
private List<HolderType> GenerateUsableList<HolderType, OriginType>(List<OriginType> originlist)
where HolderType : new()
{
// Create the usable list
List<HolderType> holderlist = new List<HolderType>();
// Convert the structlist and add every struct to the holderlist
structlist.ForEach(delegate(OriginType origintype)
{
holderlist.Add((HolderType)Activator.CreateInstance(typeof(HolderType), origintype));
});
return holderlist;
}