Das klassische PropertyGrid kennt wohl jeder Entwickler. Bekannt durch das „Properties“-Fenster in VisualStudio oder einfach als sehr produktives Control in Windows.Forms, um schnell eine Benutzeroberfläche für eigene Objekte erzeugen zu lassen. Daneben gibt es ein ähnliches Control in den meisten Control-Frameworks, welche man dazukaufen kann (z. B. von DevExpress). Neulich bin ich auf ein OpenSource-Projekt auf Codeplex gestoßen, welches in meinen Augen die eine oder andere Sache besser und hübscher macht.
Das PropertyGrid
Zunächst ein paar Worte zum normalen „PropertyGrid“. Ich bezieh mich hierbei auf das, was man eigentlich als „Standard“ bezeichnen kann und nehme dafür das „Properties“-Fenster in Visual Studio 2012 her.
Es zeigt für den Entwickler übersichtlich den Typ des Objekts, den Namen und alle Eigenschaften – mal mehr, mal weniger sinnvoll gruppiert. Für den Entwickler wie bekannt ein perfektes Werkzeug. Aber was ist für den normalen Benutzer?
Ich stoße selber auch immer wieder auf andere Programme, welche solche Grids verwenden. Auf den ersten Blick gewohnt praktisch, doch für den Benutzer wirkt das auch etwas „hin geklatscht“. Man sieht auf den ersten Blick, dass es sich im Hintergrund um eine generische Oberfläche handelt. Muss nicht zwingend ein Nachteil sein, ginge aber vermutlich besser.
Ein weiterer Punkt, der mich als Entwickler oft gestört hat, ist die Problematik, wenn sich hinter den dargestellten Eigenschaften Objekte verbergen, für die man andere Oberflächen bereitstellen muss. Es gibt viele Attribute, mit denen man das Resultat beeinflussen kann. Aus meiner Erfahrung stößt man aber dennoch oft genug an Grenzen.
Das letzte Problem, das ich hier nennen möchte, ist die simple Tatsache, dass es in Wpf gar kein Standard-Control „PropertyGrid“ gibt. Benötigt man so etwas, so ist entweder Eigenentwicklung oder eine Drittkomponente nötig.
Mein aktueller Versuch
Unten im Screenshot das Ergebnis meines aktuellsten Versuchs. Das „PropertyGrid“ ist die Oberfläche oben rechts. Selbst die Buttons sind hier im Hintergrund Eigenschaften, und zwar vom Typ DelegateCommand. Ein DelegateCommand ist im Prinzip ein Delegat und wird hier dementsprechend als Button dargestellt. Die letzte Eigenschaft „Restart animations“ ist ein Boolean und wird daher wie gewohnt als Checkbox abgebildet.
Was ist hier das Besondere? Es sieht etwas besser aus. Zudem ist der Typ DelegateCommand in einer meiner Assemblies implementiert und dadurch kennt das Control den Typ eigentlich gar nicht. Es so zu erweitern, dass hier Buttons auftauchen, war kein großes Problem. Ein anderes Beispiel im nachfolgenden Screenshot.
Das „PropertyGrid“ ist hier der komplette Bereich links von der 3D-Ansicht – ohne irgendwelche Anpassungen meinerseits. Der Unterschied zu einem normalen PropertyGrid ist nur gering, das Fehlen des „Grids“ lässt die Oberfläche aber etwas aufgeräumter erscheinen.
PropertyTools für Wpf
Die Beispiele oben konnte ich durch die „PropertyTools for WPF“ erreichen. Das ist im Prinzip das Codeplex Projekt, von dem ich eingangs geschrieben habe. Ich empfand diese Komponente als einfach und dennoch sehr mächtig, weshalb ich ihr hier einen Eintrag darüber schreibe.
Die Beispiele oben konnte ich durch die „PropertyTools for WPF“ erreichen. Das ist im Prinzip das Codeplex Projekt, von dem ich eingangs geschrieben habe. Ich empfand diese Komponente als einfach und dennoch sehr mächtig, weshalb ich ihr hier einen Eintrag darüber schreibe.
internal class RKPropertyControlFactory : DefaultPropertyControlFactory { /// <summary> /// Creates the control for a property. /// </summary> /// <param name="property">The property item.</param> /// <param name="options">The options.</param> public override FrameworkElement CreateControl( PropertyItem property, PropertyControlFactoryOptions options) { if (property.ActualPropertyType == typeof(RK.Common.Util.DelegateCommand)) { return CreateCommandButton(property, options); } return base.CreateControl(property, options); } /// <summary> /// Creates the command button for the given property. /// </summary> /// <param name="property">The property.</param> /// <param name="options">The options.</param> private FrameworkElement CreateCommandButton( PropertyItem property, PropertyControlFactoryOptions options) { Button result = new Button(); result.SetBinding(Button.CommandProperty, property.PropertyName); result.Content = property.DisplayName; return result; } }
Sehr einfaches Prinzip. Man hat hier auch über das PropertyItem Objekt die Möglichkeit, auf alle durch Attribute definierten Informationen zuzugreifen. So etwas in der Art hätte ich mir immer für PropertyGrids gewünscht!