Sichtbarkeit von Elementen über WPF Commands steuern

Das WPF Command System ist ein sehr mächtiges System. Nur gibt es da eine Sache, die mich dann doch etwas stört: Zwar kann über CanExecute und PreviewCanExecute (also Bubbling bzw. Tunneling Ereignis) festgelegt werden, ob ein Command ausgeführt werden kann oder nicht, nur wird dabei lediglich darüber entschieden, ob das jeweilige Element aktiviert oder deaktiviert ist. In manchen Fällen würde ich mir jedoch wünschen, konfigurieren zu können, was genau geschehen soll. In meinem Fall möchte ich das Element gänzlich ausblenden.

Da ich dafür keine angebotene Funktionalität finden konnte, habe ich mir selbst etwas gebaut. Ob es die schönste Lösung ist kann ich nicht sagen. Hat jemand eine bessere zur Hand, freue ich mich natürlich über eine entsprechende Mitteilung.

Gehen wir von einer einfachen Anwendung aus, die ein Menü besitzt und dieses einige Einträge. An diesen Menüeinträgen hängen Commands. Kann nun ein Command nicht ausgeführt werden, soll der Menüeintrag verschwinden. Das Basis-Markup sieht folgendermaßen aus:

   1: <DockPanel>

   2:     <Menu DockPanel.Dock="Top">

   3:         <Menu.CommandBindings>

   4:             <CommandBinding 

   5:                 Command="ApplicationCommands.Open" 

   6:                 Executed="OpenCommand_Executed"/>

   7:             <CommandBinding 

   8:                 Command="ApplicationCommands.Close" 

   9:                 Executed="CloseCommand_Executed"/>

  10:             <CommandBinding 

  11:                 Command="cmd:Commands.ExitCommand" 

  12:                 Executed="ExitCommand_Executed"/>

  13:         </Menu.CommandBindings>

  14:         <MenuItem x:Name="FileMenu" Header="File">

  15:             <MenuItem Command="ApplicationCommands.Open"/>

  16:             <MenuItem Command="ApplicationCommands.Close"/>

  17:             <Separator/>

  18:             <MenuItem Command="cmd:Commands.ExitCommand"/>

  19:         </MenuItem>

  20:     </Menu>

  21: </DockPanel>

Wer mit dem Command-System nicht vertraut ist, der findet unter anderem hier entsprechende Informationen.

Im Markup ist zu sehen, dass bis jetzt kein Handler für CanExecute erstellt wurde. Normalerweise wird dies direkt beim CommandBinding gemacht, das hilft uns allerdings nicht bei der Lösung, da wir innerhalb dieses Handlers nicht mehr auf unseren eigentlichen Menüeintrag kommen und diesen daher auch nicht unsichtbar schalten können. Es muss also eine andere Lösung her.

Das MenuItem-Element besitzt ein Attached Property names CommandManager (diese Eigenschaft besitzen auch andere Elemente). Darüber stehen dieselben Ereignisse zur Verfügung. Anstatt also das Ereignis direkt beim CommandBinding zu abonnieren, können wir dies direkt beim Menüeintrag tun (über das Attached Property) und erhalten im resultierenden Eventhandler auch Zugriff auf unser Element.

So sieht das neue XAML Markup aus:

   1: <Menu DockPanel.Dock="Top">

   2:     <Menu.CommandBindings>

   3:         <CommandBinding 

   4:             Command="ApplicationCommands.Open" 

   5:             Executed="OpenCommand_Executed"/>

   6:         <CommandBinding 

   7:             Command="ApplicationCommands.Close" 

   8:             Executed="CloseCommand_Executed"/>

   9:         <CommandBinding 

  10:             Command="cmd:Commands.ExitCommand" 

  11:             Executed="ExitCommand_Executed"/>

  12:     </Menu.CommandBindings>

  13:     <MenuItem x:Name="FileMenu" Header="File">

  14:         <MenuItem 

  15:             Command="ApplicationCommands.Open"

  16:             CommandManager.CanExecute="OpenMenuCommand_CanExecute"/>

  17:         <MenuItem 

  18:             Command="ApplicationCommands.Close"

  19:             CommandManager.CanExecute="CloseMenuCommand_CanExecute"/>

  20:         <Separator/>

  21:         <MenuItem Command="cmd:Commands.ExitCommand"/>

  22:     </MenuItem>

  23: </Menu>

Nun können wir entweder über den ersten Parameter sender auf das MenuItem oder über die Eigenschaften OriginalSource bzw,. Source der Ereignis-Argumente zugreifen:

   1: private void OpenMenuCommand_CanExecute(

   2:     object sender,

   3:     CanExecuteRoutedEventArgs e)

   4: {

   5:     FrameworkElement elem = sender as FrameworkElement;

   6:     if (FileLoader.IsLoaded)

   7:     {

   8:         if (elem != null)

   9:             elem.Visibility = Visibility.Collapsed;

  10:         e.CanExecute = false;

  11:     }

  12:     else

  13:     {

  14:         if (elem != null)

  15:             elem.Visibility = Visibility.Visible;

  16:         e.CanExecute = true;

  17:     }

  18:  

  19:     e.Handled = true;

  20: }

Was passiert hier? Es gibt einen statischen Typ FileLoader, der verschiedene Möglichkeiten (als Mock-Objekt) zur Verfügung stellt. So werden die Möglichkeiten angeboten, eine Datei zu öffnen bzw. wieder zu schließen. Über die Eigenschaft IsLoaded kann der aktuelle Status abgefragt werden. Je nachdem, wie diese Eigenschaft gesetzt ist, wird nun auch der jeweilige Menüeintrag angezeigt, oder nicht.

Aussehen tut es im Endeffekt so:

Wer sich dieses Beispiel ansehen möchte, der kann dieses natürlich herunter laden und testen:

Download

Noch mehr Tipps und Tricks

Die angebotene Trickkiste hat wieder eine Aktualisierung erfahren. Die Silverlight-Anwendung blieb dieselbe, jedoch habe ich an den Inhalten geschraubt. Ab sofort stehen auch Inhalte zu:

  • Windows Presentation Foundation (WPF)
  • Silverlight

zur Verfügung.

Über eine bequeme Suche nach Tags werden die einzelnen Tipps und Tricks in einer übersichtlichen Liste mit Teaser dargestellt. So fällt es einfach, den richtigen Eintrag zu finden.
Meinungen, Wünsche, usw. werden natürlich jederzeit gerne entgegen genommen.

SQL Server Management Studio und Vista: Fehler 29506

Nachdem es mir heute mein SQL Server Management Studio Express zerrissen hat konnte nur mehr ein Uninstall und ein Reinstall helfen. Denkste! Die Neuinstallation endete nach kompletten Durchlauf im Fehler 29506.

Mit ein wenig Recherche (man glaubt gar nicht, wie viele dieses Problem noch haben) kam ich auf die Lösung – eigentlich einfachst.

Einfach die Command Line mit Adminstratorrechten ausführen und so das Setup starten. Die Installation läuft ohne Probleme durch. So einfach kann es sein.

Fehler der Datenbindung schnell finden

Wer Datenbindung in seinen WPF-Anwendungen häufig benötigt, wird kennen, wie mühsam die Suche nach einem Fehler sein kann. Dabei bietet das .NET Framework hilfen, um derartigen Fehlern schnell auf die Spur zu kommen. Ganz ohne Tools.


Im .NET Framework 3.5 gibt es die Klasse PresentationTraceSources aus dem NamespaceSystem.Diagnostics. Dieses bietet uns die Möglichkeit, Traces von bestimmten Bereichen anzapfen zu können. Es werden zwei Wege geboten, auf diese Traces zuzugreifen:

  • Durch die Registrierung des Startup-Ereignisses der Application können die notwendigen Angaben in dessen Eventhandler getätigt werden.
  • Die Angabe der Traces kann auch über die Applikations-Konfigurations-Datei vorgenommen werden. Dies bietet den Vorteil, dass diese Funktion ohne großem Aufwand aktiviert bzw. deaktiviert werden kann.

Aber sehen wir uns dazu ein Beispiel an, welches die entsprechenden Angaben via Code tätigt.

Dazu verwenden wir ein Fenster mit einem DockPanel und einer ListView mit drei Spalten. Daran sollen Daten gebunden werden.

   1: <DockPanel>

   2:     <ListView x:Name="PeopleList">

   3:         <ListView.View>

   4:             <GridView>

   5:                 <GridViewColumn

   6:                     Header="ID"

   7:                     DisplayMemberBinding="{Binding Id}"/>

   8:                 <GridViewColumn

   9:                     Header="LastName"

  10:                     DisplayMemberBinding="{Binding Lastname}"/>

  11:                 <GridViewColumn

  12:                     Header="FirstName"

  13:                     DisplayMemberBinding="{Binding FirstName}"/>

  14:             </GridView>

  15:         </ListView.View>

  16:     </ListView>

  17: </DockPanel>

Um die Daten zu halten, wird eine Klasse Person verwendet:

   1: public class Person

   2: {

   3:     public Int64 Id { get; set; }

   4:     public String FirstName { get; set; }

   5:     public String LastName { get; set; }

   6: }

Hier fällt vielleicht auf, dass das Binding für die Eigenschaft LastName via XAML fehlerhaft angegeben wurde. In diesem einfachen Fall ist es nicht schwer, den Fehler zu finden. Bei komplexeren Aufgaben ist schon wesentlich mehr Aufwand notwendig.

Um dem Problem einfach auf die Spur zu kommen, wird das Startup-Ereignis der Anwendung registriert. Dies passiert in der Datei App.xaml:

   1: <Application x:Class="PresentationTraceDemo.App"

   2:     xmlns="..."

   3:     xmlns:x="schemas.microsoft.com/winfx/2006/xaml"

   4:     StartupUri="MainWindow.xaml"

   5:     Startup="Application_Startup">

   6:     <Application.Resources>

   7:  

   8:     </Application.Resources>

   9: </Application>

Im Eventhandler verwenden wir nun PresentationTraceSources, um die Ablaufverfolgung für die Datenbindung zu nutzen. Dazu leiten wir diese auf unsere Konsole um und defnieren einen Level. Dieser definiert, welche Daten aufgefangen und geschrieben werden:

   1: private void Application_Startup(

   2:     object sender,

   3:     StartupEventArgs e)

   4: {

   5:     PresentationTraceSources.DataBindingSource.Listeners.Add(

   6:         new ConsoleTraceListener());

   7:     PresentationTraceSources.DataBindingSource.Switch.Level =

   8:         SourceLevels.Critical : SourceLevels.Error : SourceLevels.Warning;

   9: }

Wenn wir nun die Anwendung starten, ist sie folgendermaßen zu sehen:

Es ist schön zu sehen, dass die Spalte LastName nicht befüllt wurde. Zwar einfach zu erkennen, werfen wir jetzt allerdings einen Blick in die Konsole. Hier sollte nun eine Nachricht zu finden sein, die uns auf einen Fehler in der Datenbindung aufmerksam macht:

System.Windows.Data Error: 39 :

<br />BindingExpression path error: 'Lastname' property not found on 'object' ''Person' (HashCode=23686174)'.

<br />BindingExpression:Path=Lastname; DataItem='Person' (HashCode=23686174);

<br />target element is 'TextBlock' (Name=''); target property is 'Text' (type 'String')

Damit können nun auch komplexere Fehler gefunden werden.

Fazit

Es lohnt sich auf jeden Fall, sich auch die weiteren Möglichkeiten von PresentationTraceSources anzusehen, da darüber sehr viele hilfreiche Informationen bezogen werden. Viele der vorhandenen Tools greifen ebenfalls auf diese Quelle zu.

Nachfolgend stehe eine Demoanwendung zur Verfügung, die obiges Beispiel abbildet. Es lohnt sich auch ein Blick in die MSDN. Dort ist zudem zu finden, wie obiges via Applikations-Konfigurations-Datei konfiguriert werden kann.

Bist du es leid für andere nach Lösungen zu suchen?

Bist du in der Community aktiv? Dann werden die Fragen, die sehr schnell durch eine Suche in der bevorzugten Suchmaschine beantwortet werden könnten, ein gewisses Frustpotential aufwerfen. Bekannt? Wenn ja, dann empfehle ich den nachfolgenden Link:

letmegooglethatforyou.com/

Wie es funktioniert, zeigt dieser Link:

letmegooglethatforyou.com/?q=letmegooglethatforyou&l=1

Sehr feine Sache!

PS: Wann gibt es eigentlich "Let me Live that for you"? ;-)

Der Benutzer spricht: Qualität, Usability und Versprechen

Der Benutzer hat es in vielen Fällen wirklich nicht einfach. Qualität, die es oft nicht gibt, Usability, die einem das Leben nur schwerer macht und Versprechen, die nicht eingehalten werden.

Aber wie sieht das ein Benutzer wirklich? Seht und hört selbst:

Video wurde entfernt.

Raum zur Verbesserung dürfte also noch genügend vorhanden sein … traurig aber in vielen Fällen wahr …

Google Analytics is watching you …

Benutzerverhalten werden ja schon im großen Rahmen über die Suchseite, AdWords und weiteren Diensten gesammelt und analysiert. Aber anscheinend reicht das nicht aus. Immerhin gibt es jetzt Google Analytics. Damit erhalten Website-Betreiber eine quasi kostenlose Möglichkeit, Statistiken über ihre Websites zu erhalten – und Google erfährt wieder etwas mehr über uns …

Programmierer – Habe ich das Zeug dazu?

Wie werde ich ein guter Programmierer? Welches Wissen muss ich mir aneignen? Was macht einen guten Programmierer aus? Welche Programmiersprache soll ich verwenden?

Diese und weitere Fragen werden sehr oft gestellt und meist erkenne ich aus der Fragestellung, dass in vielen Fällen wenig Wissen und wenig Erfahrung im Hintergrund schlummert. Grund dafür ist meist das junge Alter. Nichts desto trotz sind einige Punkte zu beachten, will man wirklich professionelle Programme schreiben.

Wissen ist Macht

Nicht nur Wissen ist Macht. Informationen zum richtigen Zeitpunkt zu finden ist ein sehr wichtiger Bestandteil. Im heutigen Zeitalter stellen Google und Co. sehr gute Suchhilfen zur Verfügung um relativ schnell an die gewünschte Information zu gelangen. Hierfür empfiehlt es sich allerdings, die angebotenen Hilfen der jeweiligen Betreiber gut durchzulesen und auch ein wenig zu testen. Damit kann die Trefferquote stark erhöht werden.
Weiters bieten die Hersteller von Programmiersprachen meist umfangreiche Communities bzw. Hilfeseiten an. Diese bieten gute Einführungs-, als auch Hintergrundinformationen.

Konsequent, aufnahmefähig und lösungsorientiert

Diese Eigenschaften sollten von der entsprechenden Person auf jeden Fall mitgebracht werden. Sicherlich macht es Spaß, dass eine oder andere Spielchen zu programmieren. Man muss jedoch ständig darauf achten, am Ball zu bleiben, sich neue Technologien anzusehen und vor allem Erfahrung zu sammeln.

Oft wird einfach nur in den Tag hineinprogrammiert. Es ist ja einfach und man kann sich teilweise den Sourcecode aus dem Internet besorgen und schnell ist damit ein Programm zusammenkopiert. Dies ist allerdings keine Lösung, will man ein guter Programmierer werden. Sourcecode zu kopieren macht dann Sinn, wenn man daraus lernen will. Beim nächsten Mal sollte man das Problem eigenständig lösen können. Natürlich sollte Vorhandenes genutzt werden – jedoch sollte man auch wissen wie es funktioniert.

Und die Programmiersprache?

Die Programmiersprache ist nebensächlich. Viele machen daraus jedoch einen Glaubenskrieg. Vor allem auf die Frage welche Programmiersprache denn verwendet werden soll, entbrennt eine heftige Diskussion zu diesem Thema. Dem Einsteiger hilft das meist recht wenig. Im Grunde kann ich an dieser Stelle sagen, dass sich die unterschiedlichen VB-Dialekte sehr einfach zu erlernen sind. Jedoch sollte in der heutigen Zeit auf jeden Fall von Beginn an die objektorientierte Programmierung (OOP) erlernt werden. Dies ist essentiell. Prinzipiell würde ich an dieser Stelle zu C#, Java oder Delphi raten.

Styleguides und Co.

Styleguides sind Richtlinien, die beschreiben, wie Sourcecode, Namensgebung etc. auszusehen haben. Man sollte sich recht früh einen entsprechenden Styleguide heraussuchen und sich diesen angewöhnen. Die Vorteile liegen darin, dass der Sourcecode strukturierter aufgebaut wird, die Namensgebung konsistent gestaltet und somit die Möglichkeit auch im Team arbeiten zu können gesteigert wird. Der Sourcecode wird lesbarer und leichter zu verwalten.

Conclusio

In der heutigen Zeit werden viele Anforderungen an Programmierer gestellt. Auf vielen Gebieten ist großes Wissen notwendig. Selbständigkeit beim Erlernen einer Programmiersprache bzw. der Grundlagen ist genauso gefragt wie Teamfähigkeit. Der notwendige Aufwand ein guter Programmierer zu werden ist sehr hoch. Wissensdurst vorausgesetzt.

Cookie-Einstellungen
Auf dieser Website werden Cookie verwendet. Diese werden für den Betrieb der Website benötigt oder helfen uns dabei, die Website zu verbessern.
Alle Cookies zulassen
Auswahl speichern
Individuelle Einstellungen
Individuelle Einstellungen
Dies ist eine Übersicht aller Cookies, die auf der Website verwendet werden. Sie haben die Möglichkeit, individuelle Cookie-Einstellungen vorzunehmen. Geben Sie einzelnen Cookies oder ganzen Gruppen Ihre Einwilligung. Essentielle Cookies lassen sich nicht deaktivieren.
Speichern
Abbrechen
Essenziell (1)
Essenzielle Cookies werden für die grundlegende Funktionalität der Website benötigt.
Cookies anzeigen