Kalender
<<  Oktober 2014  >>
MoDiMiDoFrSaSo
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789
blettner , eingetragen am 17. März 2009, 16:36

Manchmal können ganz einfache Dinge dafür sorgen, dass man sich stundenlang den Kopf zerbricht. Mir ist es mit dem TreeView in WPF so gegangen.

Folgende Situation: Ich habe einen TreeView mit mehreren Knoten und Elementen. Wird ein Element selektiert, sollte ein dazugehörendes Tab (im Hauptformular) aktiv werden. Dazu hab ich einen Event implementiert, den ich im SelectedItemChanged Event des TreeViews aufrufe.

Das Verhalten, das ich mir hier erwartet hätte ist, dass der Knoten den ich ausgewählt habe, selektiert ist und der jeweilige Tab angezeigt wird. Der Tab wurde richtig angezeigt, nur im Treeview wurde der Parentknoten als selektiert angezeigt und nicht der, den ich ausgewählt habe.

Der Grund für das Ganze ist, dass mein Event eine Aktion in einem anderen Formular auslöst. Das führt dazu, dass der TreeView den Focus verliert bevor er mit seinen internen Eventhandlings fertig geworden ist.

Die Lösung sieht nun folgendermassen aus:

Dispatcher.BeginInvoke(MySelectionChanged, 
                  System.Windows.Threading.DispatcherPriority.Background, 
objArg);

Mein Event wird also nicht direkt ausgeführt, sondern mit Hilfe des Dispatchers, dem ich eine eher niedrige Priorität gegeben haben. Damit wird sichergestellt, dass der TreeView seine interne Verarbeitung abschliessen kann und dann der Event ausgeführt wird.

Quelle: MSDN Forum

blettner , eingetragen am 7. März 2009, 23:05

WPF bietet den Vorteil, dass jedes Elemente, jedes Control in seiner Art der Darstellung jeglichen Gegebenheiten angepasst werden kann. Die meisten Controls unterstützen von Haus aus eine Menge Einstellungsmöglichkeiten, die deren Aussehen verändern können. Ein Control bei dem das meiner Meinung nach nicht wirklich der Fall ist, ist das Treeview Control. Dieser wurde, was die Funktionalität betrifft, auf einem absoluten Minimum gehalten. Das Mindeste was man sich noch wünschen hätte können, wäre Icons für Knoten definieren zu können, so wie man es vom Treeview aus WinForms kennt.

Letztendlich kann man diese Funktionalität aber sehr schnell nachstellen, wie folgendes Beispiel zeigen soll.

<TreeView>
  <TreeViewItem>
     <TreeViewItem.Header>
        <DockPanel>
           <Image Width="16" Height="16" Source="folder_16.png" />
           <Label VerticalContentAlignment="Center" 
                  MinWidth="80" Content="Root" Padding="3" />
        </DockPanel>
     </TreeViewItem.Header>
     <DockPanel>
        <Image Width="16" Height="16" Source="folder_16.png" />
        <Label VerticalContentAlignment="Center" 
               MinWidth="80" Content="Folder 1" Padding="3" />
     </DockPanel>
     <DockPanel>
        <Image Width="16" Height="16" Source="folder_16.png" />
        <Label VerticalContentAlignment="Center" 
               MinWidth="80" Content="Folder 2" Padding="3" />
     </DockPanel>
   </TreeViewItem>
</TreeView>
 

Das Ergbiss sieht dann folgendermassen aus.

Treeview

Um das Ganze jetzt noch etwas dynamischer zu gestalten, könnte man das DockPanel in ein Usercontrol packen. Text und Bild anhand Parameter setzen und somit eine Funktionalität nachstellen, wie man sie gewohnt ist.

Eine andere Möglichkeit wäre einen Visuellen Style anzulegen, aber das ist eine andere Geschichte!

Als ich heute bei einer WPF Applikation eine Messagebox eingebaut habe, habe ich gemerkt, dass diese noch wie zu Windows 2000 Zeiten aussah. Kein XP, kein Vista Theme.

oldstyle

Die Lösung an sich ist sehr simpel. Man fügt ein Manifest File zu der Applikation hinzu und diese erweitert man um folgenden XML Code.

<dependency>
    <dependentAssembly>
      <assemblyIdentity type="win32"          
               name="Microsoft.Windows.Common-Controls"          
               version="6.0.0.0"          
               processorArchitecture="*"          
               publicKeyToken="6595b64144ccf1df"          
               language="*"/>
    </dependentAssembly>
</dependency>

Erst dann wird die Control Library verwendet, die auch die XP und Vista Styles enthält.

newstyle

Auf der anderen Seite frag ich mich schon, warum man in WPF immer noch auf Controls zurückgreift, die nicht die selben Visuellen Elemente verwenden, wie jene, die im VStudio Designer zur Verfügung stehen. Auf der anderen Seite, wenns nach dem hinzufügen dieses Codes funktioniert ist es auch egal.

Sollte sich also jemand mal das selbe denken, dann einfach: app.manifest hinzufügen, obigen Code einfügen und alles ist gut!

Edit 26.02.2009:

Wenn man das Ganze dann noch im Vista Style haben möchte, fügt man zusätzlich folgenden Code ein:

 

[DllImport("comctl32.dll", PreserveSig = false, CharSet = CharSet.Unicode)]
static extern TaskDialogResult TaskDialog(IntPtr hwndParent, IntPtr hInstance, string title,
                                          string mainInstruction, string content,
                                          TaskDialogButtons buttons, TaskDialogIcon icon);
 
enum TaskDialogResult {
     Ok = 1,
     Cancel = 2,
     Retry = 4,
     Yes = 6,
     No  7,
     Close = 8
}
 
[Flags]
enum TaskDialogButtons {
     Ok = 0x0001,
     Yes = 0x0002,
     No = 0x0004,
     Cancel = 0x0008,
     Retry = 0x0010,
     Close = 0x0020
}
 
enum TaskDialogIcon {
     Warning = 65535,
     Error = 65534,
     Information = 65533,
     Shield = 65532
}
 
if (System.Environment.OSVersion.Version.Major >= 6) {
     TaskDialogResult objTaskResult = TaskDialog(
new System.Windows.Interop.WindowInteropHelper(objWindow).Handle,
          IntPtr.Zero, strTitle, strText, strDescription, 
TaskDialogButtons.Ok | TaskDialogButtons.Cancel,
          TaskDialogIcon.Information);
} else {
     MessageBoxResult objMessageResult = MessageBox.Show(strText, strTitle, 
MessageBoxButton.OKCancel, MessageBoxImage.Information);
}
 
vistastyle 

Wichtig hierbei ist die OS Version zu überprüfen um bei älteren Versionen (XP und darunter) die normale MessageBox anzuzeigen. Man kann sich da aber mit einer kleinen Klasse helfen, die das automatisch macht.

Quelle: Adam Nathan - Windows Presentation Foundation Unleashed (SAMS)

blettner , eingetragen am 4. Februar 2009, 17:50

Wie in meinem letzen Post (TFS Installation – eine…) erwähnt, möchte ich hier noch einmal auf das “TFS to TFS Migration Tool” eingehen. Dieses kleine aber feine Tool kann einem schon mal das Leben erleichtern, wenn alles andere fehlschlägt (siehe TFS Installation – eine…).

Ich hatte das Problem, dass ich kein Upgrade meiner 2005’er TFS Installation durchführen konnte. Daher mußte ich den TFS 2008 neu installieren. Mit dem Tool konnte ich dann sehr einfach meine Source Control Items von der alten auf die neue Instanz kopieren (inkl. Historie).

tfstotfsmigration

Installation:

Bei der Installation muß man einen User angeben, mit dem das Tool auf den TFS zugreift. Dieser User muß der lokalen Administrator Gruppe zugewiesen sein. Wenn dem nicht so ist, bekommt man eine Fehlermeldung, dass die Migration nicht durchgeführt werdenkann.

Migration:

Das Migrieren von Daten läuft relativ simpel ab. Zuerst wird ein Task erstellt in welchem die jeweiligen TF Server auswählt werden. Konnte sich das Tool mit diesen verbinden, erhält man eine Liste von Projekten, die es auf den Servern gibt.

Um die Sourcecontrol Items zu migrieren, muß es auf dem neuen Server ein Projekt geben, zu welchem diese zugeordnet werden. Wählt man dieses aus, erhält man noch die Möglichkeit, ein Verzeichnis zu wählen, in welchem die neuen Elemente angelegt werden.

Ist das erledigt, kann man den Migrations-Task starten.

Einschränkungen:

Bei der Benutzung dieses Tools sollte man sich im klaren sein, dass es sich um eine Beta Version handelt. Man erkennt es z.B. daran, dass man angelegte Tasks nicht mehr bearbeiten kann. Um diese zu verändern muß der Task gelöscht und neu erstellt werden. Ausserdem ist mir aufgefallen, dass ein Source Control Verzeichnis nicht übernommen wurde. Habe aber nicht überprüft ob das Problem nicht schon im alten TFS vorhanden war.

Alles in allem läuft es aber sehr gut und eigentlich ist es die letzte Möglichkeit seine Daten zu retten, sollte beim Upgrade der Installation etwas schief gehen oder das Upgrade überhaupt nicht funktionieren.

Download auf Codeplex.

blettner , eingetragen am 27. Januar 2009, 16:28

Prelude:

Schon seit längerem hatte ich geplant, den Teamfoundation Server bei mir in der Firma auf die aktuelle Version zu upzudaten. Da ich mich noch an die letzte Installation recht gut erinnern konnte, habe ich mich bis jetzt eigentlich gestreubt das zu machen. Aber nachdem ich gerade Zeit hatte, das SP1 auch schon längere Zeit veröffentlich ist, wollte ich das jetzt machen. In Summe hat mich dieses Vorhaben ca. 5 Arbeitstage gekostet. Warum? Na fangen wir mal an…

P.S: Das wird keine Installationsanleitung, von denen gibt es viele (siehe auch am Ende des Posts) und wenn man sich an den “Installation Guide” hält, sollte es ohne Probleme funktionieren… Ok, wenn es so wäre, würde es nicht so viele Posts dazu geben!

Intro:

Ich möchte hier noch schnell auf meine vohandene Konfiguration eingehen:

Data Tier:

SQL2005 mit eingespielten SP3

Client Tier:

Windows Server 2003
Reporting Services 2005 ink. SP3
Teamfoundation Server 2005 SP1

Der Client in ein Image welches am Virtual Server 2005 läuft, Datenbank läuft auf einem anderen Server.

Akt 1: Upgrade der vorhandenen Installation

Bevor man überhaupt daran denkt das Upgrade zu starten, sollte man seine vorhandene Installation mittels des Best Practize Analyzers auf vorhandene Fehler überprüfen. Erst wenn hier keine Fehler angezeigt werden, kann man daran denken das Upgrade durchzuführen.

In meinem Fall wurden keine Fehler angezeigt und ich war guter Hoffnung, dass das ein Vorhaben in der Dauer von 1 – 2 Stunden wird. Ich hab noch ein Backup sämtlicher Datenbanken durchgeführt und auch das Image auf dem der TFS läuft gesichert. Ohne einer DB und Client Sicherung sollte man ebenfalls nicht anfangen!!

Nachdem nun alle Vorbereitungen durchgeführt wurden (ja, ich habe im TFS Installation Guide nachgelesen was zu tun ist),  habe ich die CD eingelegt und das Setup gestartet. Es wurde auch alles brav erkannt, der Server auf dem sich die Datenbank befindet, Reporting Services usw. Also habe ich das Update gestartet, lief die ersten 10 Minuten ohne weiteres…

doch dann: “TF30059: Fatal error while initializing web service”. Was ist denn da jetzt los!? Hab dann nach kurzer Suche gefunden, dass das ein Problem mit einem Login sein könnte. Alle Logins überprüft, Best Practize Analyzer nochmal laufen lassen, wieder keine Fehler gefunden. Setup nochmal gestartet – wieder der selbe Fehler in Kombination mit einem anderen der die Reporting Services betraf.

Wieder in Google gesucht – wobei ich bei einer Lösung etwas schmunzeln musste: Man sollte doch das TFS 2008 SP1 installieren, dann würde alles funktionieren. Da frag ich mich halt, auf was soll ich das installieren, wenn noch nicht mal die normale Installation durchgelaufen ist!?

Also zurück an den Start, sämtliche Datenbanken rückgesichert und auch das Image am Virtual Server wiederhergestellt (um das nicht immer schreiben zu müssen, wird das mit Start abgekürzt).

Bei meinem zweiten Upgrade Versuch, bin ich einen Schritt weitergekommen. Da ist zumindest das Setup durchgelaufen und ich habe mir schon gedacht, dass ich es geschafft habe. Hehe, denkste. Gscheit wie ich bin, wollte ich auch gleich das SP1 installieren, hab das Setup gestartet und was war? Natürlich hat es während der Installation abgebrochen und das System in einen inkonsistenten Zustand hinterlassen. DB war auf Stand von SP1, Client war gar nichts mehr…

Start

Dritter Versuch, Installation durchgelaufen… diesmal hab ich das Service Pack nicht mehr eingespielt um nicht wieder alles kaputt zu machen. Starte mein Visual Studio, Verbinde mich zum TFS und was kommt!?  Eine Fehlermeldung, dass die Liste der Projekte nicht abgefragt werden kann und ich mich mit meinem Administrator in Verbindung setzen soll. *Kopfschüttel*

Start 

Hab mir jetzt die aktuellste Version der Installationsanleitung von der MS Seite runtergeladen und nochmal alles überprüft… das Setup gestartet: “TF30059: Fatal error while….”

Start

Weil ich nicht gleich aufgebe, folgten hier noch einige Versuche mit mehr oder weniger der selben Fehlermeldung (manchmal auch in Kombination mit anderen…).

Irgendwann hat es mir gereicht und ich habe beschlossen, dass es wohl kein Upgrade geben wird.

Akt 2: Neue installation des TFS 2008

Nachdem meine Upgrade Versuche letztendlich erfolglos blieben, habe ich beschlossen den TFS neu aufzusetzen. DB Server war ja vorhanden, daher mußte nur der Client Teil neu gemacht werden. Bei einem Virtual PC Image ist das schnell erledigt (da hatte ich schon was vorbereitet). Nachdem alle aktuellen Updates eingespielt ware habe ich begonnen die Prerequisits einzurichten und zu Installieren.

Nachdem meine Datenbank ein SQL Server 2005 war, habe ich die Reporting Services von SQL 2005 installiert (so wie es in der Anleitung steht). Als die Installation beendet war und die Services liefen, startete ich wieder mal die Installation.

Habe den Datenbank Server angegeben, auf “Weiter” geklickt und gewartet, gewartet… noch immer gewartet (schon etwas skeptisch geworden)…

Fehler, es konnte keine Verbindung zu den Reporting Servces hergestellt werden. Man solle überprüfen, ob sie laufen und ob der User berechtigt ist darauf zuzugreifen. In der Installationsanleitung steht nichts davon, dass man einen User zuweisen muß!? Komisch dachte ich mir und hab den beiden Reporting Services Accounts den Installationsuser zugewiesen und das Setup wieder gestartet. Siehe da, sie wurden erkannt und ich konnte mit der Installation fortfahren. Lief auch soweit alles gut (bei den PreChecks gab es keinen Fehler), bis naja… dieses blöde Popup am Bildschirm auftauchte, bevor der Fortschrittsbalken sein Ende erreicht. Anscheinend wurden die Reporting Services nicht gefunden.

donkey

Ungefähr so fühlte ich mich gerade und ich glaub mein Gesichtsausdruck war dem sehr ähnlich.

Hab noch im Google gesucht was die Ursache hätte sein können aber letzendlich zurück an den…

Start

Bei den nächsten drei bis vier Installationen trat immer wieder der selbe Fehler auf… einmal noch eine kleine Abwandlung, dass nämlich Reporting Services und die DB von der Version unterschiedlich seien und Reporting Services deshalb nicht Initialisiert werden könne. Wieder Eselsblick, hab doch beides von der selben DVD installiert!?!?

Um es in den Worten unseres Ex-Kanzlers zu sagen (für alle die es nicht wissen, Willi Molterer war gemeint): ES REICHT!

Akt 3: Neue installation ganz anders 

Nachdem ich mit der Installation so nicht weiterkam habe ich folgendes gemacht (um das Ganze etwas abzukürzen)

  • Das vohandene Image gelöscht und durch eine Neues ersetzt
  • Das Teamfoundation Server Service Pack 1 mit dem normalen Setup gemerged (steht im Installationsdokument wie man das macht)
  • Auf dem Datenbank Server eine neue SQL2008 Instanz erstellt (daher auch der Merge des Service Pack, da der TFS erst damit mit dem SQL Server 2008 kann)
  • Auf dem Client die SQL 2008 Reporting Services installiert (ohne noch zusätzlich Rechte vergeben zu haben)
  • Das Setup des TFS gestartet

Man wird es kaum glauben, aber das hat funktioniert.

Akt 4: Security, Security und nochmals Security

Nachdem alles fertig installiert war, fügte ich jene Benutzer, die mit dem TFS arbeiten sollten, zu den jeweiligen Gruppen (Licensed User,…) hinzu. Setzte die Berechtigungen bei den Reporting Services und auch in Sharepoint. Danach erstellte ich mein erstes Projekt – bis hierhin funktionierte alles wunderbar.

Dann wollte ich ein zweites Projekt anlegen – Fehler: “TF30224: Failed to retrieve projects from the report server. Please check that the SQL Server Reporting Services Web and Windows services are running and you have sufficient privileges for creating a project.” Ich überprüfte das, und konnte mich mit allen Usern zu den Reporting Services verbinden, konnte alle Berichte aufmachen.

Zu diesem Zeitpunkt versuchte ich mich auch von einem anderen Rechner zum TFS zu verbinden – das scheiterte mit der Fehlermeldung: “TF31004: Could not connect to Team Foundation Server”.

Nochmal alles überprüft, Benutzer im TFS, Benutzer in den Reporting Services und Benutzer in den Sharepoint Services… ware alle angelegt.

Die Lösung dieses Problems hat mich ca. 4h gekostet. Sobald man jenen Benutzern auch Rechte auf dem TFS Rechner gibt (lokal), klappt die Verbindung. Es können Projekte angelegt werden und auch auf alle Ressourcen kann man zugreifen. Verstehen tu ich das Ganze zwar nicht, aber so funktionierts!!

Akt 5: TFS Migration Tool

Das einzige was wirklich von Anfang an funktionierte, war das TFS Migration Tool. Damit konnte ich meine Source Control Items von dem einen auf den anderen Server migrieren. Das Tool wäre an sich noch viel mächtiger (zwei Server synchronisieren usw.), aber für mich hat das gereicht.

Hinweis: mit dem Tool kann man nur Sourcecontrol Items und Work Items migrieren. Alles andere ist nicht möglich.

Downloaden kann man es hier.

Outro

Letztendlich hat mich das (wie schon erwähnt) fünf Arbeitstage gekostet. Bei der Installation des TFS kann einen schon der Frust packen, aber aufgeben wollte ich auch nicht! Auf alle Fälle werde ich es mir beim Nächsten mal genau überlegen, ob ich das mache oder nicht. Wenn alles funktionieren würde, wär es ja kein Problem. Aber wenn man die Menge an Posts liest, die es zu Thema Setup und damit verbundenen Problemen mit dem TFS gibt, bin ich in Zukunft vorsichtiger!

Links & Anleitungen

Während ich nach den verschiedensten Fehlern gesucht habe, habe ich auch einige interessante und an sich ganze gute Anleitungen gefunden. Vielleicht helfen sie jemanden weiter, der mehr Glück mit seiner Installation hat als ich!

Kurze Anleitung:
http://olausson.net/blog/2007/12/03/UpgradeTFS2005To2008.aspx

Eine ausführliche Anleitung mit sämtlichten Links zu den nötigen downloads:
http://blogs.imeta.co.uk/nrees/archive/2008/11/07/upgrading-dual-server-tfs-2005-to-tfs-2008-sp1.aspx

TFS Migration Tool

http://www.codeplex.com/tfstotfsmigration

Auf ein interessantes Theme bin ich vor kurzem gestossen. Wie kann man eine WPF Applikation so steueren, dass Forms auf verschiedenen Physischen Screens dargestellt werden. Nach ein wenig suchen bin ich auf eine einfache Lösung gestossen.

Im System.Windows.Forms Namespace (die Referenz muß in einer WPF Applikation per Hand hinzugefügt werden) gibt es die Klasse Screen. Diese liefert alle nötigen Informationen wie z.b: welcher Screen der Hauptschirm ist, eine Collection aller zur Verfügung stehenden Screens sowie deren Auflösung und Namen.

Folgendes Codestück zeigt, wie man eine Form auf den jeweiligen Screen anzeigen kann.

List<Screen> objScreenList = Screen.AllScreens.ToList();
 
foreach (Screen objActualScreen in objScreenList) {
   Window1 objForm = new Window1();
 
   objForm.WindowStartupLocation = WindowStartupLocation.Manual;
   objForm.Left = Convert.ToDouble(objActualScreen.Bounds.Location.X + 20);
   objForm.Top = Convert.ToDouble(objActualScreen.Bounds.Location.Y + 20);
   objForm.label1.Content = "Screen: " + objActualScreen.DeviceName;
   objForm.Show();
}

 

Mittels AllScreens erhält man eine Liste sämtlicher Screens die zu diesem Zeitpunkt zur Verfügung stehen. In diesem Beispiel wird eine Testform für jeden Screen erstellt und mittels der Screenproperties auf diesen positioniert. In einem Label wird der jeweilige Devicename angezeigt.

 

image

Letztendlich sollte auf jedem Screen das obige Fenster angezeigt werden.