Blog Home  Home Feed your aggregator (RSS 2.0)  
artiso Blog - Know-How
Neues rund um's Thema .Net
 
 Friday, April 04, 2008

Über das PropertyGrid-Control habe ich ja mehrmals gebloggt (z.B. hier). Dieses Control verwendie ich recht häufig um z.B. den Inhalt eigene Konfigurations-Klassen zu editieren. Zusammen mit der XML-Serialisierung lassen sich so sehr flexible Konfigurationsmöglichkeiten schaffen.

Nun hatte ich die Anforderung eine dynamische Datenstruktur an ein PropertyGrid zu binden. Da stand ich zunächst vor einem Problem. Bisher habe ich nur Objekte mit Properties unterschiedlicher Typen an das PropertyGrid gebunden. Nun habe ich eine Liste von Objekten, die die Elemente im PropertyGrid beschreiben. Wie aber diese an das PropertyGrid binden?

Das schöne ist, das das PropertyGrid sich hier als sehr flexibel erweist. Man muss folgende Schritte durchführen:

  1. Man brauch eine Klasse für ein einzelnes Property
  2. Dann brauchen wir eine Collection für diese Properties. Diese leiten wir von CollectionBase und ICustomTypeDescriptor ab und implementieren die Interfaces. Entscheidend ist hier die Methode GetProperties. Hier werden nun ine PropertyDescriptionCollection aus unseren Properties aufgebaut. Diese Methode ruft das PropertyGrid auf um sich dieProperties zu besorgen, die es rendern soll. Hier können wir nun also von einer belibigen Datenstruktur die benötigten
    Informationen für das PropertyGrid aufbauen.
  3. Dafür brauch wir jetzt noch einen cCustomPropertyDescriptor. Diesen leiten wir von PropertyDescriptor ab und implementieren es.
  4. Nun können wir unsere Properties aufbauen und an das PropertyGrid binden. Ich habe das CustomPropertyGrid als eigenes Control angelegt. Der Code ist nun sehr simpel:
   1: private void Form1_Load(object sender, EventArgs e)
   2: {
   3:     cPropertyCollection props = new cPropertyCollection();
   4:     props.Add(new cPropertyItem("BoolValue", "This is a boolean value", false, true, "Properties"));
   5:     props.Add(new cPropertyItem("StringValue", "This is a string value", false, "Test123", "Properties"));
   6:     props.Add(new cPropertyItem("Folder", "Path for folder", false, "", "Path"));
   7:  
   8:     this.artisoPropertyGrid1.SelectedObject = props;
   9: }


Damit erhält man folgendes Ergebnis. Man sieht die dynamisch angelegten Properties mit ihrem Name, in die Kategorien untergliedert und mit der Beschreibung. Das PropertyGrid wählt automatisch die gewohnten Controls abhängig vom Datentyp aus.

image

Dis ist schon ganz nett. Ich möchte aber für das Folder-Property einen entsprechenden Editor angeben können. Bei statischen Klassen vrwendet man einfach Attribute, aber bei dynamischen? Dazu wird die verfügbare Dokumentation sehr, sehr dünn. Hierzu haben wir auf der Property-Klasse eine Attribute-Arary. Diese Attribute können wir nun in der GetProperties-Klasse an den cCostomPropertyDescriptor übergeben. Der Aufbau der Properties sieht dann so aus:

   1: private void Form1_Load(object sender, EventArgs e)
   2: {
   3:     cPropertyCollection props = new cPropertyCollection();
   4:     props.Add(new cPropertyItem("BoolValue", "This is a boolean value", false, true, "Properties"));
   5:     props.Add(new cPropertyItem("StringValue", "This is a string value", false, "Test123", "Properties"));
   6:     props.Add(new cPropertyItem("Folder", "Path for folder", false, "", "Path",
   7:         new TypeConverterAttribute(),
   8:         new EditorAttribute(typeof(System.Windows.Forms.Design.FolderNameEditor), typeof(System.Drawing.Design.UITypeEditor))));
   9:  
  10:     this.artisoPropertyGrid1.SelectedObject = props;
  11: }

 

Nun kann man im Feld für den Wert für das Property "Folder" auf einen Button klicken und erhält einen Dialog zur Auswahl eines Verzeichnisses.

image

Friday, April 04, 2008 11:17:09 PM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    |   | 
 Tuesday, March 18, 2008

In diesem White Paper werden verschiedene Konzepte für das Requirement Management mit Visual Studio und einigen 3rd Party Tools beschrieben. Leider fehlt bei den 3rd Party Tools unser artiso WorkitemManager ;-)

http://www.microsoft.com/downloads/details.aspx?FamilyId=EEF7BB41-C686-4C9F-990B-F78ACE01C191&displaylang=en#filelist

Tuesday, March 18, 2008 12:27:12 AM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    |   | 
 Saturday, October 06, 2007

Objekte und Listen lassen sich jetzt in C# 3.0 sehr schön initialisieren. War bisher um ein relativ einfaches Objekt zu initialisieren sehr viel Code erforderlich, hat sich das nun deutlich verkürzt:

Bisher:

List<cProduct> Products = new List<cProduct>();

cProduct Product = new cProduct();
Product.ID = 1;
Product.BusinessDevelopmentComment = "";
Product.MarketingComments = "";
Product.VersionDescriptions = new List<cProductVersionDescription>();
Product.INNs = new List<cProductINNItem>();

cProductVersionDescription VersionDescription = new cProductVersionDescription();
VersionDescription.ID = 1;
VersionDescription.LastPCMDate = DateTime.Now;
VersionDescription.LastPCMDecision = "Go";
VersionDescription.NPV = 689.54;
VersionDescription.ProductID = 1;
VersionDescription.ProductVersionID = 1;
VersionDescription.VersionName = "Version1";
Product.VersionDescriptions.Add(VersionDescription);

cProductINNItem INN = new cProductINNItem();
INN.INN = 8;
INN.Dosage = 1.5;
INN.DosageUnit = 1;
INN.Volume = 1;
INN.Comment = "Test-Comment";
INN.INNOrder = 1;
Product.INNs.Add(INN);

INN = new cProductINNItem();
INN.INN = 2;
INN.Dosage = 2.5;
INN.DosageUnit = 2;
INN.Volume = 2;
INN.Comment = "Test-Comment2";
INN.INNOrder = 2;
Product.INNs.Add(INN);
 

Neu mit C#3.0:

List<cProduct> Products = new List<cProduct>
{
    new cProduct{ ID = 1, BusinessDevelopmentComment = "", MarketingComments = "", 
        VersionDescriptions = new List<cProductVersionDescription>
        {
            new cProductVersionDescription{ ID=1, LastPCMDate=DateTime.Now, LastPCMDecision="Go", NPV=689.54, ProductID=1, ProductVersionID=1, VersionName="Version1"}
        }, 
        INNs = new List<cProductINNItem>
        {
            new cProductINNItem{ INN=8, Dosage=1.5, DosageUnit=1, Volume=1, Comment="Test-Comment", INNOrder=1},
            new cProductINNItem{ INN=2, Dosage=2.5, DosageUnit=2, Volume=2, Comment="Test-Comment2", INNOrder=2}
        }
    }
};

 

Bisher konnte man den Code noch etwas vereinfachen, indem man einen entsprechenden Konstruktor für die Objekte erstellt hat, in dem die Initialisierungswerte übergeben werden konnten. Hier bietet die neue Version aber den Vorteil, dass diese leichter zu leesen ist, da die Parameter hier entsprechend bezeichnet sind. Beim Konstruktor musste immer Intellisense zu Hilfe genommen werden um herauszufinden, um welchen Parameter es sich handelt.

Saturday, October 06, 2007 5:17:22 PM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    |  |   | 
 Thursday, August 16, 2007

Scott Mitchell hat 75 Tutorials zum Thema Data Access mit ASP.Net 2.0 geschrieben. Hier ist praktisch alles an Technologie beschrieben, was für die Programmierung von datenbankbasierten Webanwendungen mit ASP.Net 2.0 notwendig ist. Einzig LINQ wird momentan noch ausgespart. Eine wirklich tolle Sammlung an guten Informationen.

image

Data Access Tutorials : The Official Microsoft ASP.NET 2.0 Site

Thursday, August 16, 2007 10:06:18 AM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    |  |  |  |   | 
 Thursday, July 26, 2007

Hat man ein typisiertes DataSet und arbeitet darin mit mehreren TableAdaptern, dann stellt sich die Frage, wie Updates auf diesen TableAdaptern in eine Transaktion zusammengefasst werden können. Das Problem dabei ist, dass jeder TableAdapter seine eigene Connection nutzt. Es gibt grundsätzlich zwei Lösungsansätze:

  1. Man verwendet den TransactionScope aus dem System.Transactions-Namespace. Diese Vorgehensweise hat allerdings den Nachteil, dass die verschiedenen Connections nur über eine Distributed Transactions verwaltet werden können. Das ist nicht unbedingt das Nonplusultra was die Performance angeht und eigentlich ja auch mit Kanonen auf Spatzen geschossen, da typischerweise alle TableAdapter ja auf die gleiche Datenbank gehen dürften und damit die Ditributed Transactions etwas überkandidelt sind.
  2. Man verwendet eine Connection für alle TableAdpater. Hierzu gibt es glücklicherweise die Möglichkiet, dass man die Connection der Tableadapter austauschen kann. Man kann z.B. einfach die Connection des ersten TableAdapters allen anderen zuweisen und dann auf dieser Connection mit BeginTransaction eine neue Transaktion beginnen und diese dann mit Commit bzw. RollBack abschließen. Alternativ kann man natürlich auch manuell eine Connection erzeugen und diese dann allen TableAdaptern zuweisen.

Eine sehr schöne Beschreibung dieser Lösungsansätze hat John Waters unter folgendem Link veröffentlicht: ADO.NET : Getting TableAdapters to participate in transactions

Thursday, July 26, 2007 5:05:23 PM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    |   | 
 Saturday, April 28, 2007

 Wie man mit .net (VB2005) auf das Active Directory zugreift und dort Benutzer ausliest und verwaltet zeigt, der Blog-Beitrag von Armin Stockner.

Link to Armin Stockner : Active Directory with VB2005

Saturday, April 28, 2007 9:16:53 AM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    | 
 Wednesday, April 11, 2007

Bei der Dotnet Usergroup Bremen wurde das Thema in einem kleinen Artikel ausführlich diskutiert.

Link to DOTnet Usergroup Bremen

Danke an Chris für den Link

Wednesday, April 11, 2007 10:11:25 AM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    | 
 Monday, October 30, 2006

Ein wirklich gutes Dokument zum Thema Databinding in WinForms mit Visual Studio 2005 findet sich unter

http://www.windowsforms.net/Samples/Go%20To%20Market/Data%20Binding/DataBinding%20FAQ.doc#_Toc117313112

Monday, October 30, 2006 11:49:20 AM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    | 
 Sunday, September 17, 2006

10 häufige Fallstricke bi der Veröffentlichung von ASP.Net Webseiten und deren Vermeidung, zum Teil auch der technische Hintergrund werden in folgendem Artikel beschrieben:

http://www.microsoft.com/germany/msdn/library/net/aspnet/StoerungsfreiAusgefuehrteSitesDurchVermeidenDieserZehnVerbreitetenASPNETFehlerquellen.mspx?mfr=true

Sunday, September 17, 2006 9:44:47 PM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    |  |   | 

Bei der Erstellung von UIs sollte darauf geachtet werden, dass möglichst wenig Funktionalität in der Benutzeroberfläche selbst implementiert wird. Das folgende Entwurfsmuster beschreibt eine Vorgehensweise:

http://www.microsoft.com/germany/msdn/library/architecture/EntwurfsmusterModelViewPresenter.mspx?mfr=true

Sunday, September 17, 2006 9:40:07 PM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    |   | 
 Saturday, September 16, 2006

Der Artikel beschreibt wie unter ASP.Net 2.0 Ressoucen eingesetzt werden und wie sich damit Web-Anwendungen lokalisieren lassen.

http://www.microsoft.com/germany/msdn/library/net/aspnet/RessourcenUndLokalisierungInASPNET20.mspx?mfr=true

Saturday, September 16, 2006 9:46:35 PM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    | 

Die Verwaltung von Konfigurationseinstellungen hat sich in .net 2.0 gegenüber .net 1.1 geändert. Es stehen Funktionen zum Schreiben von Konfigurationsparameter und auch benutzerspezifische Konfigurationsparameter zur Verfügung. Die Verwendung der Konfigurationeinstellungen unter .net 2.0 beschreibt der Artikel http://msdn.microsoft.com/vcsharp/default.aspx?pull=/library/en-us/dnvs05/html/SettingsCS_RL.asp

Saturday, September 16, 2006 9:40:12 PM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    | 
 Tuesday, August 29, 2006

.Net Applikationen werden normalerweise Just in Time compiliert. Durch eine Vorkompilierung können sich Vorteile in Punkto Performance uns Speichernutzung ergeben. Dazu bietet das .net Framework das Tool NGen. Wie dieses Tool eingesetzt werden kann und was dabei zu beachten ist beschreibt dieser deutschsprachige Artikel.

http://www.microsoft.com/germany/msdn/library/net/DieLeistungsvorteileDurchNGen.mspx?mfr=true

Tuesday, August 29, 2006 7:57:56 AM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    | 
 Friday, August 25, 2006

Das Buch beschreibt das Thema Threading in C' recht ausführlich und lässt sich auch als PDF herunterladen.

http://www.albahari.com/threading/

Friday, August 25, 2006 7:03:36 PM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    | 
 Thursday, August 24, 2006
Ich habe im Speicher ein DataView mit ca. 22000 Datensätzen. Aus diesem DataView musste ich nun innerhalb einer Schleife 55 Abfragen machen. Dazu zwei Methoden:

dvINNs.RowFilter = "ProductDSID = " + drProducts["ProductDSID"];
foreach (DataRowView drINN in dvINNs)
{
...
}

oder

foreach (DataRow drINN in dvINNs.Table.Select("ProductDSID = " + drProducts["ProductDSID"]))
{
...
}

Ich habe eine Zeitmessung durchgeführt. Dies ergab für Methode I 1,5 Sek und für Methode II 0,03 Sek. D.h. der Select ist um Faktor 50 (in meinem Beispiel) schneller als der RowFilter.

Thursday, August 24, 2006 7:50:19 AM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    | 
 Tuesday, August 22, 2006

Oft möchte man den Monatsnamen eines Datums in der jeweiligen Landessprache des Anwenders ausgeben. Dies kann man einfach mit einer Zeile Code bewerkstelligen:

string MonthName = Application.CurrentCulture.DateTimeFormat.MonthNames[DateTimeValue.Month-1];

Alternativ kann man auch die Kurzform der Monate über die Eigenschaft AbbreviatedMonthNames abfragen.

Will man eine spezifische Sprache zur Ausgabe verwenden, kann man dies natürlich auch tun indem man einfach das entsprechende CultureInfo-Objekt verwendet:

CultureInfo ci = new CultureInfo("de-DE");
ci.DateTimeFormat.MonthNames[MonthID];

Tuesday, August 22, 2006 3:59:59 PM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    | 
 Monday, August 14, 2006

MSDN Solve ist die Lösung für alle Entwickler, die praxis-orientierte Hilfestellungen bei typischen Programmier-Herausforderungen suchen. MSDN Solve liefert verständliche Antworten auf immer wiederkehrende Fragen aus dem IT-Alltag und sorgt dafür, dass Sie Stolperfallen in Software-Projekten künftig leicht umschiffen.

http://www.microsoft.com/germany/msdn/solve/default.mspx

Monday, August 14, 2006 11:04:04 AM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    |   | 

Die aktuelle Bildschirmauflösung abzufragen ist in .NET denkbar einfach, möchte man jedoch alle verfügbaren Auflösungen erfragen und eventuell sogar eine neue Auflösung setzen, muss man auf die Win32 API-Mittel zurückgreifen. Dieser Beitrag stellt eine Klasse zur Verfügung mit der mit jeweils einer Zeile Code über die verfügbaren Auflösungen iteriert werden bzw. eine neue Auflösung festgelegt werden kann

http://www.codegod.de/WebAppCodeGod/Main.aspx?pid=168

Monday, August 14, 2006 6:47:42 AM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    |   | 
 Wednesday, August 09, 2006

Ein wenig bekanntes Control ist das FlowLayoutPanel, das in VS 2005 standardmäßig enthalten ist. Mit diesem Control kann man Unterelemente in einer fließenden Ansicht darstellen wie das z.B. auch von Web-Seiten bekannt ist. Sie möchten eine Liste von Textboxen die untereinander stehen? Kein Problem mit dem FlowLayoutPanel. Sie können eine beliebige Richtung wählen (von rechts nach links, von oben nach unten etc.). Passen nicht alle Control in die Reihe, wird automatisch ein Umgruch eingefügt. Damit ist das FlowLayoutPanel wesentlich flexibler als man diese Funktion z.B. mit Docking erreichen könnte. Vor allem bei dynamisch generierten Control leistet das FlowLayoutPanel gute Dienste!

Wednesday, August 09, 2006 1:48:34 PM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    |   | 

Oft möchte man Daten, die aus Excel in die Zwischenablage kopiert wurden, in der Anwendung verarbeiten. Dies geht recht einfach, da die Excel-Daten in der Zwischenablage einfach als CSV-Format vorliegen.

string ExcelValue = "";
IDataObject ClipboadData = Clipboard.GetDataObject();
if (ClipboadData.GetDataPresent(DataFormats.CommaSeparatedValue))
{
   
StreamReader ExcelReader = new StreamReader((Stream)ClipboadData.GetData(DataFormats.CommaSeparatedValue));
   
while (!ExcelReader.EndOfStream)
   {
      ExcelValue = ExcelReader.ReadLine();
   }
}

Man holt sich die Daten aus der Zwischenablage und prüft diese, ob sie im CSV-Format vorliegen. Dann kann man mit Hilfe eines StreamReaders die Daten lesen. Die Daten kommen dann in einem Format wie z.B. 5,8;8,9;7,5. Das lässt sich nun problemlos in der eigenen Anwendung verarbeiten.

Wednesday, August 09, 2006 1:37:59 PM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    |   | 
 Tuesday, August 08, 2006

Um von generischen Objekten den Typ abzufragen kann man folgenden Code verwenden:

Dictionary<string, int> MyObject = new Dictionary<string, int>();
Type T = MyObject.GetType();
Type[] Ts = T.GetGenericArguments();

Dieser Code liefert ein Array zurück, das im ersten Element System.String und im zweiten System.Double enthält.

Weitere Infos unter http://msdn2.microsoft.com/en-us/library/b8ytshk6.aspx

Tuesday, August 08, 2006 1:33:43 PM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    |   | 
 Friday, August 04, 2006

Eine sehr umfangreiche Link-Liste zu den 3 Hauptthemen von .Net 3.0 gibt es unter:

Teil 1: Windows Presentation Foundation
Teil 2: Windows Communication Foundation
Teil 3: Windows Workflow Foundation

Friday, August 04, 2006 6:10:58 PM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    |   | 
 Tuesday, August 01, 2006

Eine Reihe von interessanten Artikel findet man unter http://www.theserverside.net/tt/articles/index.tss

Tuesday, August 01, 2006 7:05:21 PM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    |   | 
 Friday, July 28, 2006
 Thursday, July 27, 2006

Statt try-catch-finally gibt es auch noch eine Alternative mit Hilfe sog. Scopes.

http://blog.veloursnebel.de/PermaLink,guid,fb472ac8-d855-4224-a2e0-ddf758492b17.aspx

Thursday, July 27, 2006 7:04:14 PM (Mitteleuropäische Zeit, UTC+01:00)