Property Value Editoren für Silverlight-Steuerelemente
Einführung
Dies ist Teil der Serie über Design-Zeit die Umsetzung Änderungen in Silverlight Toolkit März 2009 Veröffentlichung . Dieser Beitrag beschreibt, wie das Bearbeiten von Eigenschaften Erlebnis für Silverlight-Steuerelemente mithilfe Eigenschaftswert Editor und Typkonverter zu verbessern. Ich werde mit der Beschreibung der allgemeinen Eigenschaftenbearbeitungsarchitektur in WPF / Silverlight-Designer-Erweiterbarkeit Rahmen beginnen, dann verwenden Sie Beispiele in Silverlight Toolkit März 2009 Veröffentlichung zu zeigen, wie es gemacht wird, und einzigartige Themen / Tricks in Silverlight Entwurfszeit Entwicklung.
Eigenschaftenbearbeitungsarchitektur
Optisch Bearbeitung von Objekteigenschaften ist ein wichtiger Teil von Designern. Designer in der Regel nicht wissen, wie man Eigenschaften von benutzerdefinierten Typ (struct, Klasse oder Schnittstelle), viel weniger zu machen, eine schöne Bearbeitung Benutzeroberfläche bereitzustellen. Control-Entwickler müssen in der Regel bieten TypeConverter , PropertyValueEditor , oder beides, um Rendering / Bearbeitung UI und XAML-Serialisierung für Eigenschaften von benutzerdefinierten Typen bieten.
Der Designer erweiterbares Framework definiert drei Arten von Immobilien-Wert-Editor: Inline-Editor, erweiterte Editor und Dialog-Editor, die jeweils von einer Klasse implementiert:
Bearbeiten von UI dieser Editoren sind definiert durch DataTemplate . Das Anwesen bearbeitet wird, um Editor ausgesetzt DataContext von PropertyValue Typ. Editor UI in der Regel auf die zugrunde liegende Eigenschaft, die über eine der drei Eigenschaften bearbeitet binden PropertyValue : Wert , StringValue oder Sammlung .
PropertyValueEditor
PropertyValueEditor hält einen einzigen Inline-Editor definiert durch InlineEditorTemplate Eigentum. Inline-Editor wird im Eigenschaften-Fenster. Unten ist ein einfaches Beispiel InlineEditorTemplate , dass eine TextBox verwendet zum Anzeigen und Bearbeiten einer Eigenschaft:
x:Key ="TextBoxEditor" > <DataTemplate x: Key = "TextBoxEditor"> Text ="{Binding Path=Value}" /> <TextBox Text = "{Binding Path = Wert}" /> > </ DataTemplate>
ExtendedPropertyValueEditor
x:Key ="inlineEditor" > <DataTemplate x: Key = "inlineEditor"> Content ="..." Command ="{x:Static PropertyEditing:PropertyValueEditorCommands.ShowDialogEditor}" /> <Button Inhalt ="..." Command = "{x: Static PropertyEditing: PropertyValueEditorCommands.ShowDialogEditor}" /> > </ DataTemplate> x:Name ="slider" Value ="{Binding Path=Value}" /> <Slider x: Name = "slider" Value = "{Binding Path = Wert}" /> > </ DataTemplate>
DialogPropertyValueEditor
DialogPropertyValueEditor hat zwei Redakteuren zu: Der Inline-Editor von geerbten PropertyValueEditor , und eine zusätzliche Dialog-Editor definiert durch DialogEditorTemplate Eigentum. Der Dialog-Editor ist in der Regel von Inline-Editor via tauchte PropertyValueEditorCommands . ShowDialogEditor Befehl. Unten ist ein einfaches Beispiel:
x:Key ="inlineEditor" > < Button Content ="..." Command ="{x:Static <DataTemplate x: Key = "inlineEditor"> <Knopf Inhalt ="..." Command = "{x: Static ="Center" HorizontalAlignment ="Right" Margin ="0,0,4,4" /> < TextBox Text ="{Binding Name: "VerticalAlignment =" center "HorizontalAlignment =" right "Margin =" 0,0,4,4 "/> <TextBox Text =" {Binding
Implementieren Sie benutzerdefinierte Eigenschaften-Editor
Zur Umsetzung einer benutzerdefinierten Eigenschaft Editor für ein Silverlight-Steuerelement:
- Implementieren eines benutzerdefinierten Property-Editor-Klasse
- erben von PropertyValueEditor, ExtendedPropertyValueEditor oder DialogPropertyValueEditor
- setzen Sie den Editor-Template (s): InlineEditorTemplate , ExtendedEditorTemplate und / oder DialogEditorTemplate ;
- Verknüpfen Sie die benutzerdefinierte Eigenschaft Editor mit einer Eigenschaft eines Silverlight-Steuerelement über eine AddCustomAttributes nennen, so etwas wie
- Eine korrekt implementierte Eigenschaft Wert Editor muss folgende Anforderungen erfüllen:
- Der Wert der Eigenschaft Editor muss so ausgelegt sein, dass die Inline-Editor und erweiterte Editor Teile können unabhängig voneinander genutzt werden.
- Eine Eigenschaft, Wert-Editor darf nicht speichern Zustand. Property Wert-Editoren sind staatenlos, könnte von einem Host-Implementierung zwischengespeichert und können über mehrere Eigenschaftswerte wieder verwendet werden.
- Eine Eigenschaft, Wert-Editor darf nicht davon ausgehen, dass nur ein Wert-Editor Teil (view / inline / extended)-Steuerung aktiv ist zu einem bestimmten Zeitpunkt. Zum Beispiel könnte ein Dialogfeld sind der Ansicht, teilweise Inline-Teil, und erweiterte UI Teil aktiv zur gleichen Zeit.
- Eine Kontrolle als Teil einer Immobilie Wert-Editor implementiert darf nicht speichern Zustand. Eine Kontrolle als Teil einer Wert-Editor implementiert sollten nicht davon ausgehen, dass es nur eine Eigenschaft Wert gebunden werden. Kontrollen können recycelt, verschiedene Eigenschaftswerte ändern. Alle Informationen, die zwischengespeichert wird, sollte einfach weggespült, wenn das Datenmodell aktualisiert wird.
- Eine Kontrolle als Teil einer Immobilie Wert-Editor implementiert werden müssen keine Annahmen über den Host oder seine übergeordneten Steuerelemente. Die einzige Kommunikations-Mechanismen, die verwendet werden sollten, sind die PropertyValue Datenmodell, über die DataContext , und die Standard-Satz von Befehlen.
- Sie können mehr über das Bearbeiten von Eigenschaften Architektur und Designer erweiterbares Framework auf MSDN.
Reference Beide WPF-und Silverlight-Assemblies
Ein Design Assembly ist eine .NET / WPF Montage von Visual Studio oder Blend-geladen, aber es muss in der Regel Silverlight Baugruppen (zumindest das Silverlight-Steuerelement der Montage bietet Design-Zeit Funktionen für) Referenz. Dies kann anhand Mehrdeutigkeit für Design Montage-Projekt: es braucht manchmal die gleichen vollqualifizierten Typ in WPF und Silverlight Referenz, sagen System.Windows.FrameworkElement in beiden PresentationFramework.dll von WPF und Silverlight von System.Windows.dll. Um zu vermeiden, verwirrend Visual Studio können Sie extern alias WPF und Silverlight Verweise zu unterscheiden.
Zum Beispiel, siehe Screenshot unten für Controls.DataVisualization.Toolkit.Design Projekt in Silverlight 3 Toolkit in März 2009 Veröffentlichung :
- das Projekt Referenzen sowohl PresentationFramework und System.Windows, aber System.Windows unter Silverlight alias, anstelle des standardmäßigen globalen Pseudonyms gestattet. . Die System.Windows Referenz unter Silverlight alias ist in csproj Datei fort wie folgt:
Include ="System.Windows, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e, processorArchitecture=MSIL" > <Reference Include = "System.Windows, Version = 2.0.5.0, Culture = neutral, PublicKeyToken = 7cec85d7bea7798e, processorArchitecture = MSIL"> > False </ SpecificVersion > <SpecificVersion> false </ SpecificVersion> > ..\Binaries\System.Windows.dll </ HintPath > <HintPath> .. \ Binaries \ System.Windows.dll </ HintPath> > False </ Private > <Private> false </ Private> > Silverlight </ Aliases > <Aliases> Silverlight </ Aliases> > </ Reference>
- im Quellcode, fügen wir
extern alias Silverlight; mit SSW = Silverlight:: System.Windows;
und Referenz Silverlight FrameworkElement via SSW:: FrameworkElement.
TextBoxEditor
Es gibt einen Inline-Editor TextBoxEditor in Controls.DataVisualization.Toolkit.Design Projekt für die Anzeige und Bearbeitung von Title-Eigenschaft des Objekttyps für [Area | Bar | Bubble | Column | Line | Pie | Scatter] Series und Chart-Steuerelemente, wie unten dargestellt:
Text in Feld Titel in Fenster Eigenschaften gefüllt auf der rechten Seite zeigt automatisch in XAML und Design Ansichten in der Mitte.
Die Umsetzung der TextBoxEditor folgte der oben beschriebenen Schritte:
- TextBoxEditor ist eine Unterklasse von PropertyValueEditor. Es setzt InlineEditorTemplate in seiner Default-Konstruktor. Hier benutze ich Code statt XAML das Konstrukt DataTemplate , denn irgendwie habe ich nicht bekommen kann XAML zu bauen, und alles, was in XAML kann in C umgeschrieben # sowieso.
- Es ist mit Chart.Title in ChartMetadata.cs (siehe zugehörige Design-Time Feature-Implementierung in Silverlight Toolkit für weitere Informationen über * Metadata.cs-Dateien)
TextBoxEditor.cs:
/ / (C) Copyright Microsoft Corporation. / / Diese Quelle ist unter der Microsoft Public License (Ms-PL). / / Bitte beachten Sie http://go.microsoft.com/fwlink/?LinkID=131993 für Details. / / Alle anderen Rechte vorbehalten. using System; mit Microsoft.Windows.Design.PropertyEditing; mit System.Windows; mit System.Windows.Data; namespace System.Windows.Controls.DataVisualization.Design { / / / <summary> / / / Simple TextBox Inline-Editor. / / / </ Summary> public partial class TextBoxEditor: PropertyValueEditor { / / / <summary> / / / Preserve die Konstruktorprototyp aus PropertyValueEditor. / / / </ Summary> / / / <param Name="inlineEditorTemplate"> Inline-Editor Vorlage. </ P> öffentlichen TextBoxEditor (DataTemplate inlineEditorTemplate) : Base (inlineEditorTemplate) {} / / / <summary> / / / Default-Konstruktor baut die Standard-TextBox Inline-Editor-Template. / / / </ Summary> öffentlichen TextBoxEditor () { (TextBox)); FrameworkElementFactory textBox = new FrameworkElementFactory (typeof (TextBox)); Binding binding = new Binding (); ); binding.Path = new PropertyPath ("Value"); binding.Mode = BindingMode.TwoWay; textBox.SetBinding (TextBox.TextProperty, Bindung); DataTemplate dt = new DataTemplate (); dt.VisualTree = textBox; InlineEditorTemplate = dt; } } }
CultureInfoEditor
Mein Kollege RJ schrieb Inline-Editor CultureInfoEditor für TimePicker.Culture Eigentum, weil die Standard-Editing-Erfahrung für CultureInfo in Blend führt zu ungültigen XAML. Unten Screenshot zeigt die CultureInfoEditor verwendet eine ComboBox für alle CultureInfo-Display und generiert rechts XAML.
CultureInfoEditor ist ein komplexeres Beispiel als TextBoxEditor, wirklich zeigt, wie die zugrunde liegenden Immobilie mit Editor über DataContext Eigenschaft zugeordnet ist.
CultureInfoEditor.cs:
/ / (C) Copyright Microsoft Corporation. / / Diese Quelle ist unter der Microsoft Public License (Ms-PL). / / Bitte beachten Sie http://go.microsoft.com/fwlink/?LinkID=131993 für Details. / / Alle sonstigen Rechte CultureInfoEditor : PropertyValueEditor { /// <summary> /// The ComboBox being used to edit the value. /// </summary> private ComboBox _owner; /// <summary> /// Preserve the constructor prototype from PropertyValueEditor. /// </summary> /// <param name="inlineEditorTemplate">Inline editor template.</param> public CultureInfoEditor(DataTemplate inlineEditorTemplate) : base (inlineEditorTemplate) { } /// <summary> /// Default constructor builds a ComboBox inline editor template. /// </summary> public CultureInfoEditor() { // not using databinding here because Silverlight does not support // the WPF CultureConverter that is used by Blend. FrameworkElementFactory comboBox = new FrameworkElementFactory( typeof (ComboBox)); comboBox.AddHandler( ComboBox.LoadedEvent, new RoutedEventHandler( (sender, e) => { _owner = (ComboBox) sender; _owner.SelectionChanged += EditorSelectionChanged; INotifyPropertyChanged data = _owner.DataContext as INotifyPropertyChanged; if (data != null ) { data.PropertyChanged += DatacontextPropertyChanged; } _owner.DataContextChanged += CultureDatacontextChanged; })); comboBox.SetValue(ComboBox.IsEditableProperty, false ); comboBox.SetValue(ComboBox.DisplayMemberPathProperty, "DisplayName" ); comboBox.SetValue(ComboBox.ItemsSourceProperty, CultureInfo.GetCultures(CultureTypes.SpecificCultures)); DataTemplate dt = new DataTemplate(); dt.VisualTree = comboBox; InlineEditorTemplate = dt; } /// <summary> /// Handles the SelectionChanged event of the owner control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="System.Windows.Controls.SelectionChangedEventArgs"/> /// instance containing the event data.</param> private void EditorSelectionChanged( object sender, SelectionChangedEventArgs e) { // serialize with name. object DataContext = _owner.DataContext; DataContext .GetType() .GetProperty( "Value" , BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty) .SetValue(DataContext, ((CultureInfo)_owner.SelectedItem).Name, new object [] { }); } /// <summary> /// Handles the PropertyChanged event of the context object. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="System.ComponentModel.PropertyChangedEventArgs"/> instance containing the event data.</param> private void DatacontextPropertyChanged( object sender, PropertyChangedEventArgs e) { // deserialize from name. if (e.PropertyName == "Value" ) { object value = sender .GetType() .GetProperty( "Value" , BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty) .GetValue(sender, new object [] { }); if ( value != null ) { if ( value is string ) { CultureInfo setCulture = new CultureInfo( value .ToString()); _owner.SelectedItem = setCulture; } } } } /// <summary> /// Called when the context is changed. /// </summary> /// <param name="sender">The sender.</param> /// <param name="e">The <see cref="System.Windows.DependencyPropertyChangedEventArgs"/> instance containing the event data.</param> private void CultureDatacontextChanged( object sender, DependencyPropertyChangedEventArgs e) { INotifyPropertyChanged old = e.OldValue as INotifyPropertyChanged; if (old != null ) { old.PropertyChanged -= DatacontextPropertyChanged; } INotifyPropertyChanged newDataContext = e.NewValue as INotifyPropertyChanged; if (newDataContext != null ) { newDataContext.PropertyChanged += DatacontextPropertyChanged; } } } } {/ / / Summary / / / Editor für CultureInfo / / / </ summary> / / / <remarks> unterstützt derzeit keine Bindung von XAML, um den Editor </ remarks> public class CultureInfoEditor:.. PropertyValueEditor {/ / / <summary> / / / Der ComboBox verwendet wird, um den Wert zu bearbeiten / / / </ summary> private ComboBox _owner;.. / / / summary / / / Preserve die Konstruktorprototyp aus PropertyValueEditor / / / </ summary> / / / <param name="inlineEditorTemplate"> Inline-Editor Vorlage </ param> public CultureInfoEditor (DataTemplate inlineEditorTemplate):. base (inlineEditorTemplate) {} / / / summary / / / Default-Konstruktor erstellt eine ComboBox Inline-Editor-Template. / / / </ summary> public CultureInfoEditor () {/ / nicht mit databinding hier, weil Silverlight nicht unterstützt / / die WPF CultureConverter, die durch Mischung verwendet wird FrameworkElementFactory comboBox = new FrameworkElementFactory (typeof (ComboBox));. comboBox.AddHandler ( ComboBox.LoadedEvent, neue RoutedEventHandler ((sender, e) => {_owner = (ComboBox) sender; _owner.SelectionChanged + = EditorSelectionChanged; INotifyPropertyChanged data = _owner.DataContext als INotifyPropertyChanged;! if (data = null) {data.PropertyChanged + = DatacontextPropertyChanged;} _owner.DataContextChanged + = CultureDatacontextChanged;})); comboBox.SetValue (ComboBox.IsEditableProperty, false); comboBox.SetValue (ComboBox.DisplayMemberPathProperty, "DisplayName"); comboBox.SetValue (ComboBox.ItemsSourceProperty, CultureInfo.GetCultures (CultureTypes.SpecificCultures)); DataTemplate dt = new DataTemplate (); dt.VisualTree = comboBox; InlineEditorTemplate = dt;.} / / / summary / / / Verarbeitet das SelectionChanged-Ereignis des Eigentümers control / / / </ summary > / / / <param name="sender"> Die Quelle des Ereignisses. </ param> / / / <param name="e"> Die <siehe cref="System.Windows.Controls.SelectionChangedEventArgs"/> / / / Instanz mit der Event-Daten </ param> private void EditorSelectionChanged (object sender, SelectionChangedEventArgs e) {/ / mit dem Namen serialize Objekt DataContext = _owner.DataContext;... DataContext GetType () GetProperty ("Value", BindingFlags.. .. Public | BindingFlags.Instance | BindingFlags.GetProperty) SetValue (DataContext, ((CultureInfo) _owner.SelectedItem) Name, new object [] {});} / / / summary / / / Verarbeitet das PropertyChanged-Ereignis des Kontextobjekt. / / / </ summary> / / / <param name="sender"> Die Quelle des Ereignisses. </ param> / / / <param name="e"> Die <siehe cref = "System. ComponentModel.PropertyChangedEventArgs "/>-Instanz mit den Ereignisdaten. </ param> private void DatacontextPropertyChanged (object sender, PropertyChangedEventArgs e) {/ / vom Namen deserialisieren. if (e.PropertyName ==" Value ") {object value = Absender. .. GetType () GetProperty ("Value", BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty) GetValue (Absender, new object [] {}); if (value = null) {if (Wert string) { CultureInfo setCulture = new CultureInfo (Wert ToString ().); _owner.SelectedItem = setCulture;.}}}} / / / summary / / / Wird aufgerufen, wenn der Kontext verändert / / / </ summary> / / / < param name = "Absender"> Der Absender. </ param> / / / <param name="e"> Die <siehe cref="System.Windows.DependencyPropertyChangedEventArgs"/> Instanz mit den Ereignisdaten. </ param> private void CultureDatacontextChanged (object sender, DependencyPropertyChangedEventArgs e) {INotifyPropertyChanged alt = e.OldValue als INotifyPropertyChanged; if (alt = null) {old.PropertyChanged -= DatacontextPropertyChanged;} INotifyPropertyChanged newDataContext = e.NewValue als INotifyPropertyChanged;! if (newDataContext = null ) {newDataContext.PropertyChanged + = DatacontextPropertyChanged;}}}}
ExpandableObjectConverter
Wie eingangs diskutiert, neben benutzerdefinierte Eigenschaft Wert-Editoren, manchmal kann man mit geeigneten Typkonverter, gute Bearbeitungsmöglichkeiten und XAML-Serialisierung bieten. Ein Beispiel dafür ist ColumnSeries.DependentRangeAxis: es ist der IRangeAxis Art, Blend weiß nicht, wie um sie zu bearbeiten, so zeigt es DependentRangeAxis als schreibgeschützt in Properties Panel. Durch die Zuordnung ExpandableObjectConverter zu ColumnSeries.DependentRangeAxis:
b.AddCustomAttributes ( Extensions.GetMemberName <ColumnSeries> (x => x.DependentRangeAxis) (ExpandableObjectConverter))); neue TypeConverterAttribute (typeof (ExpandableObjectConverter))); b.AddCustomAttributes ( Extensions.GetMemberName <ColumnSeries> (x => x.IndependentAxis) (ExpandableObjectConverter))); neue TypeConverterAttribute (typeof (ExpandableObjectConverter)));
Mischung zeigt eine neue Schaltfläche neben dieser Eigenschaft in Properties Panel; wenn darauf geklickt wird, öffnet es die Select-Object Dialog mit der Eigenschaft der Typ IRangeAxis gefiltert:
Abschluss
Blend und Silverlight zusammen ermöglichen es Entwicklern, erstaunliche UI gegen echte Steuerelemente erstellen direkt, so ist es sehr wichtig, dass die Kontrolle Entwickler Designer Erfahrung nehmen als Teil der allgemeinen Kontrolle Design und Implementierung. Nachdem eine benutzerdefinierte Eigenschaft Editor, der schöne Bearbeitung UI bietet und erzeugt richtige XAML ist ein wichtiger Bestandteil des Designers zu erleben. Hoffentlich post hilft Ihnen zu verstehen, wie Sie benutzerdefinierte Eigenschaft Editoren erstellen. Vielen Dank!








Recent Comments