...sollte man sich mal die AsyncPostbackTriggers anschaen, evtl. liegt das Proble dort begraben. Aber erst mal der Reihe nach. Ich hatte eine Web-Seite, die sich plötzlich nicht mehr aufrufen lies. Ich habe unterschiedliche Fehler erhalten. Mit dem IIS wurde einfach angezeigt, dass die Seite nicht verfügbar ist, im Debug meldete Visual Studio eine OutOfMemoryException und der Developer Web Server ist gleich mal abgeschmiert. Nach einigem Suchen haben wir dann das Problem entdeckt. Auf der Seite war ein AsyncPostbackTrigger auf eine Textbox eingetragen. Diese Textbox wurde aber irgendwann entfernt. Dies scheint das oben beschriebene Problem ausgelöst zu haben. Vielleicht hat ja mal jemend einen ähnlichen Fehler und kann ihn mit dieser Info schnell beheben.
Mit Hilfe der neuen Extension Methods in C# 3.0 können einfache Matrizenoperationen ganz einfach als Methoden auf bestehende Objekttypen eingefügt werden. Ich habe hier mal ein Beispiel mit SortedDictionaries. Diese Extension Method erlaubt das addieren zweier Matrizen. public static void AddDictionary(this SortedDictionary<int, decimal> resultDictionary, SortedDictionary<int, decimal> insertDictionary)
{
foreach (int key in insertDictionary.Keys)
{
if (!resultDictionary.ContainsKey(key))
resultDictionary.Add(key, insertDictionary[key]);
else
resultDictionary[key] += insertDictionary[key];
}
}
Der Aufruf gestaltet sich dann sehr einfach:
SortedDictionary<int, decimal> a = new SortedDictionary();
SortedDictionary<int, decimal> b = new SortedDictionary();
//Werte in Dictionaries einfügen
a.AddDictionary(b);
Ich finde die Extension Methods ne feine Sache. Natürlich sind auch beliebige andere Operationen möglich.
Des TFS SDK enthält ein Control um Workitems in Winforms zu bearbeiten. Dieses Control löst damit das Problem, wie die hochflexible Struktur von Workitems in einer eigenen Anwendung dargestellt und bearbeitet werden kann. Mit dem neuen TFS SDK 2008 gibt es allerdings ein kleines Problem beim Einsatz des Controls. Wird das Control in eine Winform eingebaut, kommt es zu einer NullReferenceException. Object reference not set to an instance of an object. Dieses Problem konnte ich bei mir umgehen, indem ich nicht die DLL aus dem SDK sondern aus dem TeamExplorer. Ich habe die beiden DLLS, die ich hier ausgetauscht habe hier zum Download bereitgestellt.
Über die TFS-API kann der Namen eines TFS-Servers einfach abgefragt werden. Dazu kann folgender Code verwendet werden: private TeamFoundationServer tfs; NetworkCredential account = new NetworkCredential(user, password); tfs = new TeamFoundationServer(server, account); string ServerName = tfs.Name; Dabei habe ich allerdings folgendes Problem festgestellt: Der Servername ist nicht konsistent. Ist der Server im Team-Explorer noch nicht geristriert, enthält der Servername auch den Port. Nachdem der Server im Team-Explorer dann registriert wurde, wird nur noch der Server-Name zurückgegeben. Das sollte man auf jeden Fall berücksichtigen, wenn man mit dem Name-Property vom tfs arbeitet.
Unter Access 2003 gabe es Access-Datenbankprojekte (*.adp) mit denen man wunderbar auf bestehende SQL-Datenbanken zugreifen konnten. Sind diese mit Access 2007 verloren gegangen? Das nicht, aber sie sind jetzt gut versteckt. Um ein Datenbankprojekt mit Access 2007 anzulegen geht man wie folgt vor: - Access ganz normal starten
- Access fragt nun nach einer Vorlage für eine neue Datei. Hier das Icon "Blank Database" auswählen.
- Im rechten Bereich kann man nun den Dateiname angeben. Hier den File-Dialog öffnen.
- In diesem Dialog kann man nun als Dateityp "Microsoft Office Access Projects" auswählen.
- Wenn mann dann auf den "Create"-Button klickt kann man noch auswählen, ob man sich zu einer bestehenden Datenbank verbinden möchte oder eine neue anlegen will. Der Rest dürfte dann wieder vertraut erscheinen.
Aus dem Fenster mit Fehlermeldungen und Wahrnungen im Visual Studio heraus kann man direkt Workitems auf dem Team Foundation Server anlegen. Dazu einfach die entsprechende Zeile mit der rechten Maustaste anklicken und im Kontextmenü "Create Work Item" wählen. Es werden automatisch Informationen in den Titel und den Verlauf übernommen, wobei meiner Meinung nach die Details eher in das Beschreibungs-Feld gehören als in den Verlauf. 
Schick ist es, wenn man in der Anwendung demBenutzer die verfügbaren SQL-Server als Auswahl anzeigt. Die kann man mit folgendem Code bewerkstelligen: using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace SQLInstances
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
DataTable dataTable = System.Data.Sql.SqlDataSourceEnumerator.Instance.GetDataSources();
foreach (DataRow datarow in dataTable.Rows)
{
string datasource = datarow["ServerName"].ToString();
if (datarow["InstanceName"] != DBNull.Value)
{
datasource += String.Format("\\{0}", datarow["InstanceName"]);
ComboBox1.Items.Add(datasource);
}
DataGridView1.DataSource = dataTable;
}
}
}
}
Das Beispiel gibt die verfügbaren SQL-Server in einem GridVie aus.
Um auch Zuisatzinformationen wie Version etc. zu erhalten, muss auf dem SQL-Server der SQL-Browser laufen:

Unter http://entwickler-press.de/ kann man einen Adventskalender öffnen. Hinter jedem Türchen steht ein e-Book zum kostenlosen Download. Aber Achtung das Türchen geht immer nur an dem jeweiligen Tag auf.
Durch Zufall habe ich gerade herausgefunden, dass man im IE auch mehrere Startseiten eintragen kann. Einfach in der Liste mehrere zeilen mit den verschiedenen URLs eingeben. Die werden dann beim Start alle geöffnet. 
Folgende Anforderung: Ich möchte in einer Tabelle, die über die gesamte Bildschirmbreite geht, den Inhalt einer Zelle scrollbar haben. Mein Ansatz: Ich mache in die Tabellenzelle ein DIV mit Overflow:auto Problem: Das funktioniert zwar im FireFox, aber nicht im IE. Der IE geht wohl her und schaut sich den Inhalt des DIVs an und macht die Tabelle dann so breit, dass der gesamte Inhalt reinpasst und berücksichtigt dabei nicht, dass das DIV ja auch scrollen könnte. Dieser Effekt tritt auf, wenn das DIV eine prozentuale Breite hat. Folgender Code verdeutlichd das Problem. Das obere DIV verhällt sich korrekt, da es nicht in eine Tabelle eingebettet ist. Bei den unteren beiden tritt aber das beschriebene Problem auf. <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="ValuePlanner_2008.Web.ProductArea.WebForm1" %>
<html>
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div style="width: 100%; overflow: auto">
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa<br />
<br />
</div>
<script language="javascript" type="text/javascript"> 1: 2: function fnRefreshScrollPosition(source) 3: { 4: document.getElementById("staticUnits").scrollLeft = source; 5: } 6: </script>
<div style="width: 100%">
<table style="width: 100%">
<tr>
<td style="width: 100%; height: 50px;">
<div id="staticUnits" style="width: 100%; overflow: auto;">
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb<br />
<br />
</div>
</td>
</tr>
</table>
<table style="width: 100%">
<tr>
<td style="width: 100%; height: 50px;">
<div id="units" style="width: 100%; overflow: auto;" onscroll="fnRefreshScrollPosition(this.scrollLeft);">
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<br />
<br />
</div>
</td>
</tr>
</table>
</div>
</form>
</body>
</html>
Lösung 1: Ich kann den DIVs eine feste Breite geben. Aber eigentlich will ich ja, dass der gesamte zur Verfügung stehende Platz genutzt wird und wenn dieser nicht ausreicht gescrollt wird. Um das zu erreichen müsste ich über ein Resitze-Event die Breite der Tabellenzeile ermitteln und diese dann jedesmal auf die DIVs anwenden. Das wird aber schnell sehr hässlich wenn Margins etc. mit berücksichtigt werden müssen.
Lösung 2: Ich positioniere die DIVs einfach absolut. Dann werden Sie nicht mehr als Inhalt der Tabelle berücksichtigt und die Tabelle erstreckt sich über genau 100% der Breite. Gut nutzen kann man hier den Effekt, dass die Positionsangaben bei absoluter Poistionierung sich immer auf den Container, also in unserem Fall auf die Tabellenzelle beziehen. Ein Stolperstein dabei ist, dass das DIV natürlich auch keinen Einfluss mehr auf die Höhe der Tabellenzelle hat. Diese muss man nun explizit angeben, ich habe da einfach mal 50px vorgegeben. Der Code sieht dann so aus. Hier scrollen nun alle 3 DIVs wie gewünscht.
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="ValuePlanner_2008.Web.ProductArea.WebForm1" %>
<html>
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div style="width: 100%; overflow: auto">
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa<br />
<br />
</div>
<script language="javascript" type="text/javascript"> 1: 2: function fnRefreshScrollPosition(source) 3: { 4: document.getElementById("staticUnits").scrollLeft = source; 5: } 6: </script>
<div style="width: 100%">
<table style="width: 100%">
<tr>
<td style="width: 100%; height: 50px;">
<div id="staticUnits" style="width: 100%; overflow: auto; position: absolute">
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb<br />
<br />
</div>
</td>
</tr>
</table>
<table style="width: 100%">
<tr>
<td style="width: 100%; height: 50px;">
<div id="units" style="width: 100%; overflow: auto; position: absolute;" onscroll="fnRefreshScrollPosition(this.scrollLeft);">
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<br />
<br />
</div>
</td>
</tr>
</table>
</div>
</form>
</body>
</html>
Events in eigene WebUserControls (.ascx) einzubauen ist im Prinzip ganz einfach: 1: public event ClickEventHandler Clicked; 2: public delegate void ClickEventHandler(object sender, EventArgs e); 3: protected virtual void OnClicked(EventArgs e) 4: { 5: if (Clicked != null) 6: Clicked(this, e); 7: }
Man deviniert ein Event mit einem Eventhandler-Typ (Zeile1), definiert einen Delegaten für den Eventhandler (Zeile 2) und kann dann eine Methode definieren, die den Event auslöst. Diese Methode ruft man dann auf, wenn das Event ausgelöst werden soll.
Wenn man das UserControl in eine Seite einbaut kann man jetzt im CodeBehind ganz einfach einen Eventhandler auf den Event registrieren und fertig:
this.ucButton.Clicked += new ClickEventHandler(ucButton_Clicked);
Auch im Markup kann man den Event angeben, vorausgesetzt man hat den entsprechenden Eventhandler angelegt.
<uc3:ucButton ID="ucButton" runat="server" Text="Gross" ImageURL="~/Images/Status/GreenBox.png" OnClicked="ucButton_Clicked" /> Was bei mir aber nicht funktioniert, ist der Designtime-Support. Bei anderen Controls kann ich die Events im Property-Grid sehen und ich kann per Doppelclick auch einen Standard-Eventhandler einrichten und registrieren. Das geht bei mir nicht. Hat jemand dafür eine Lösung? Wenn ja, dann bitte her damit.
Sicher ein alter Hut, aber für mich war's gerade neu und ich finde das echt klasse. Mit CSS kann man Elemente auch mit einem Abstand zum rechten Rand positionieren. <DIV style="position:absolute; right:20px; top:350px; width:300px; height:150px;"></DIV> erzeugt ein DIV das immer exakt 20px vom Rechten Rand entfernt ist, auch nach einem Resize des Fensters. Genauc das was ich gerade brauche. Man muss dabei nur beschten, dass right offensichtlich die schwächste Einstellung ist, d.h. wenn left und width ebenfalls angegeben sind, wird right ignoriert. Wenn aber nur zwei der Werte angegeben sind, wird der dritte automatisch ermittelt, also z.B. bei left und right wird die Breite automatisch angepasst. Das selbe funktioniert natürlich auch mit top, bottom und height.
Im TFS 2008 hat Microsoft endlich die Lizenzbedingungen angepasst. Für folgende Aktionen wird nun keine CAL mehr benötigt: - Anlegen eines Workitems
- Anzeigen der Workitems, die ein Benutzer selbst angelegt hat
- Bearbeiten der Workitems außer Änderung des Status des Workitems
Damit ist es nun endlich möglich, Kunden etc. in das Projekt besser einzubinden, ohne dafür Unsummen für CALs auszugeben. adamga's WebLog : TFS for Defect Tracking! Licensing Change!!!
Bei unserem heutigen Treffen der .Net Developer-Group Ulm hatten wir einen Vortrag zum Thema SQL-Projekte. Dabei kam die Frage auf, ob man Daten einer Datenbank nicht in ein SQL-Skript exportieren kann, das dann alle Daten über Insert-Statements einfügen kann. Ich habe hierzu eine Lösung in Visual Studio 2008 gefunden und das geht so:
1.) Server Explorer öffnen und die entsprechende Verbindung rechts anklicken, dann "Publish to provider" auswählen.
2.) Dann die Datebank auswählen und darunter die Checkbox disablen (außer man will wirklich die Datenbank komplett scripten).
3.) Die nächsten Schritte sind dann soweit selbsterklären. In dieser Maske kann man dann auswählen, ob man Daten, Schema oder beides scripten möchte:
4. In dem erzeugten Script steht dan z.B. so etwas:
INSERT [dbo].[Customers] ([CustomerID], [CompanyName], [ContactName], [ContactTitle], [Address], [City], [Region], [PostalCode], [Country], [Phone], [Fax])
VALUES (N'ALFKI', N'Alfreds Futterkiste', N'Maria Anders', N'Sales Representative', N'Obere Str. 57', N'Berlin', NULL, N'12209', N'Germany', N'030-0074321', N'030-0076545')
INSERT [dbo].[Customers] ([CustomerID], [CompanyName], [ContactName], [ContactTitle], [Address], [City], [Region], [PostalCode], [Country], [Phone], [Fax])
VALUES (N'ANATR', N'Ana Trujillo Emparedados y helados', N'Ana Trujillo', N'Owner', N'Avda. de la Constitución 2222', N'México D.F.', NULL, N'05021', N'Mexico', N'(5) 555-4729', N'(5) 555-3745')
INSERT [dbo].[Customers] ([CustomerID], [CompanyName], [ContactName], [ContactTitle], [Address], [City], [Region], [PostalCode], [Country], [Phone], [Fax])
VALUES (N'ANTON', N'Antonio Moreno Taquería', N'Antonio Moreno', N'Owner', N'Mataderos 2312', N'México D.F.', NULL, N'05023', N'Mexico', N'(5) 555-3932', NULL)
INSERT [dbo].[Customers] ([CustomerID], [CompanyName], [ContactName], [ContactTitle], [Address], [City], [Region], [PostalCode], [Country], [Phone], [Fax])
VALUES (N'AROUT', N'Around the Horn', N'Thomas Hardy', N'Sales Representative', N'120 Hanover Sq.', N'London', NULL, N'WA1 1DP', N'UK', N'(171) 555-7788', N'(171) 555-6750')
INSERT [dbo].[Customers] ([CustomerID], [CompanyName], [ContactName], [ContactTitle], [Address], [City], [Region], [PostalCode], [Country], [Phone], [Fax])
VALUES (N'BERGS', N'Berglunds snabbköp', N'Christina Berglund', N'Order Administrator', N'Berguvsvägen 8', N'Luleå', NULL, N'S-958 22', N'Sweden', N'0921-12 34 65', N'0921-12 34 67')
INSERT [dbo].[Customers] ([CustomerID], [CompanyName], [ContactName], [ContactTitle], [Address], [City], [Region], [PostalCode], [Country], [Phone], [Fax])
VALUES (N'BLAUS', N'Blauer See Delikatessen', N'Hanna Moos', N'Sales Representative', N'Forsterstr. 57', N'Mannheim', NULL, N'68306', N'Germany', N'0621-08460', N'0621-08924')
INSERT [dbo].[Customers] ([CustomerID], [CompanyName], [ContactName], [ContactTitle], [Address], [City], [Region], [PostalCode], [Country], [Phone], [Fax])
VALUES (N'BLONP', N'Blondesddsl père et fils', N'Frédérique Citeaux', N'Marketing Manager', N'24, place Kléber', N'Strasbourg', NULL, N'67000', N'France', N'88.60.15.31', N'88.60.15.32')
INSERT [dbo].[Customers] ([CustomerID], [CompanyName], [ContactName], [ContactTitle], [Address], [City], [Region], [PostalCode], [Country], [Phone], [Fax])
VALUES (N'BOLID', N'Bólido Comidas preparadas', N'Martín Sommer', N'Owner', N'C/ Araquil, 67', N'Madrid', NULL, N'28023', N'Spain', N'(91) 555 22 82', N'(91) 555 91 99')
INSERT [dbo].[Customers] ([CustomerID], [CompanyName], [ContactName], [ContactTitle], [Address], [City], [Region], [PostalCode], [Country], [Phone], [Fax])
VALUES (N'BONAP', N'Bon app''', N'Laurence Lebihan', N'Owner', N'12, rue des Bouchers', N'Marseille', NULL, N'13008', N'France', N'91.24.45.40', N'91.24.45.41')
Das Script lässt sich dann wunderbar in Datenbankprojekte einbauen und in der Quellcode verwqlten. Dies bietet z.B. eine gute Möglichkeit, um Testdaten für die Durchführung von Tests mit der jeweiligen Anwendungs-Version in der Quellcode-Verwaltung zu verwalten.
In Visual Studio 2005 funktioniert das leider nicht. Dort muss auf entsprechende Tools zurückgegriffen werden, z.B. den kostenlosen Oracle SQL Developer http://www.oracle.com/technology/products/database/sql_developer/index.html der übrigens auch mit SQL-Server funktioniert 
Das Problem:
Ich habe in C# ein Objekt vom Typ System.Drawing.Color. Dieses möchte ich in einen String-Konvertieren, den ich im HTML verwenden kann. Das funktioniert gut bei benannten Farben wie z.B. "red". Dort kann man Color.Name verwenden. Aber bei nicht benannten Farben liefert dies einen ARGB-Wert mit dem HTML nichts anfangen kann. Dehalb habe ich diese kleine Mthode geschrieben:
| |