Übersicht über das Erstellen von SteuerelementenControl Authoring Overview

Dank der Erweiterbarkeit des Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF)-Steuerelementmodells ist das Erstellen neuer Steuerelemente nur selten erforderlich.The extensibility of the Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF) control model greatly reduces the need to create a new control. In bestimmten Fällen lässt sich das Erstellen benutzerdefinierter Steuerelemente dennoch nicht vermeiden.However, in certain cases you may still need to create a custom control. In diesem Thema werden die Funktionen, dank deren Sie auf das Erstellen neuer Steuerelementen in den meisten Fällen verzichten können, sowie verschiedene Modelle zum Erstellen von Steuerelementen in Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF) behandelt.This topic discusses the features that minimize your need to create a custom control and the different control authoring models in Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF). Außerdem wird in diesem Thema auch das Erstellen eines neuen Steuerelements veranschaulicht.This topic also demonstrates how to create a new control.

Alternativen zum Erstellen eines neuen SteuerelementsAlternatives to Writing a New Control

In der Vergangenheit waren Sie bei der Anpassung eines vorhandenen Steuerelements auf die Bearbeitung seiner Standardeigenschaften beschränkt. Sie konnten z.B. die Hintergrundfarbe, die Rahmenbreite sowie die Schriftgröße ändern.Historically, if you wanted to get a customized experience from an existing control, you were limited to changing the standard properties of the control, such as background color, border width, and font size. Falls Sie die Darstellung oder das Verhalten eines Steuerelements über diese vordefinierten Parameter hinaus erweitern wollten, waren Sie auf das Erstellen eines neuen Steuerelements angewiesen. Die übliche Vorgehensweise war die Vererbung von einem vorhandenen Steuerelement samt der Überschreibung der für das Zeichnen des Steuerelements zuständigen Methode.If you wished to extend the appearance or behavior of a control beyond these predefined parameters, you would need to create a new control, usually by inheriting from an existing control and overriding the method responsible for drawing the control. Diese Option steht Ihnen zwar weiterhin zur Verfügung, mit dem reichen Inhaltsmodel von WPFWPF sowie seinen Stilen, Vorlagen und Triggern können Sie jedoch die vorhandenen Steuerelemente auf eine vielfältige Art und Weise anzupassen.Although that is still an option, WPFWPF enables to you customize existing controls by using its rich content model, styles, templates, and triggers. In der folgenden Liste finden Sie Beispiele für die Verwendung dieser Funktionen zum Erstellen einer benutzerdefinierten und konsistenten Umgebung, ohne ein neues Steuerelement erstellen zu müssen.The following list gives examples of how these features can be used to create custom and consistent experiences without having to create a new control.

  • Multimediainhalte.Rich Content. Viele WPFWPF-Standardsteuerelemente unterstützen Multimediainhalte.Many of the standard WPFWPF controls support rich content. Z. B. die Content-Eigenschaft von einem Button ist vom Typ Object, theoretisch alles angezeigt werden kann, auf eine Button.For example, the content property of a Button is of type Object, so theoretically anything can be displayed on a Button. Um eine Schaltfläche ein Bild und Text angezeigt haben, können Sie ein Bild hinzufügen und eine TextBlock auf eine StackPanel und weisen Sie die StackPanel auf die Content Eigenschaft.To have a button display an image and text, you can add an image and a TextBlock to a StackPanel and assign the StackPanel to the Content property. Da die Steuerelemente visuelle WPFWPF-Elemente sowie beliebige Daten anzeigen können, ist es zwecks der Unterstützung einer komplexen Visualisierung selten notwendig, neue Steuerelemente zu erstellen oder vorhandene Steuerelemente zu ändern.Because the controls can display WPFWPF visual elements and arbitrary data, there is less need to create a new control or to modify an existing control to support a complex visualization. Weitere Informationen über das Inhaltsmodell für Button und andere Inhalte Modelle im WPFWPF, finden Sie unter WPF-Inhaltsmodell.For more information about the content model for Button and other content models in WPFWPF, see WPF Content Model.

  • Stile.Styles. Ein Style ist eine Sammlung von Werten, die Eigenschaften für ein Steuerelement darstellen.A Style is a collection of values that represent properties for a control. Mit Stilen können Sie eine wiederverwendbare Darstellung der erwünschten Gestaltung und des erwünschten Verhaltens der Steuerelemente erstellen, ohne ein neues Steuerelement erstellen zu müssen.By using styles, you can create a reusable representation of a desired control appearance and behavior without writing a new control. Nehmen wir beispielsweise an, dass Sie alle möchten Ihre TextBlock Steuerelemente roten der Schriftart Arial mit Schriftgrad 14 aufweisen.For example, assume that you want all of your TextBlock controls to have red, Arial font with a font size of 14. Sie können einen Stil als eine Ressource anlegen und die jeweiligen Eigenschaften entsprechend festlegen.You can create a style as a resource and set the appropriate properties accordingly. Und dann jede TextBlock , dass Sie Ihre Anwendung hinzufügen, werden die gleiche Darstellung aufweisen.Then every TextBlock that you add to your application will have the same appearance.

  • Datenvorlagen.Data Templates. Ein DataTemplate können Sie anpassen, wie Daten in einem Steuerelement angezeigt werden.A DataTemplate enables you to customize how data is displayed on a control. Z. B. eine DataTemplate kann verwendet werden, um anzugeben, wie Daten in angezeigt werden eine ListBox.For example, a DataTemplate can be used to specify how data is displayed in a ListBox. Weitere Beispiele finden Sie unter Übersicht über Datenvorlagen.For an example of this, see Data Templating Overview. Zusätzlich zur Anpassung der Darstellung von Daten, eine DataTemplate können Elemente der Benutzeroberfläche umfassen die bietet Ihnen ein hohes Maß an Flexibilität in benutzerdefinierte Benutzeroberflächen.In addition to customizing the appearance of data, a DataTemplate can include UI elements, which gives you a lot of flexibility in custom UIs. Z. B. durch Verwendung einer DataTemplate, können Sie erstellen eine ComboBox in dem jedes Element ein Kontrollkästchen enthält.For example, by using a DataTemplate, you can create a ComboBox in which each item contains a check box.

  • Steuerelementvorlagen.Control Templates. Viele Steuerelemente in WPFWPF verwenden eine ControlTemplate definieren die Struktur des Steuerelements und die Darstellung der getrennt von der Darstellung eines Steuerelements über die Funktionalität des Steuerelements.Many controls in WPFWPF use a ControlTemplate to define the control's structure and appearance, which separates the appearance of a control from the functionality of the control. Sie können die Darstellung eines Steuerelements erheblich ändern, durch Neudefinieren der ControlTemplate.You can drastically change the appearance of a control by redefining its ControlTemplate. Nehmen wir z.B. an, dass Sie ein Steuerelement wie eine Ampel aussehen lassen möchten.For example, suppose you want a control that looks like a stoplight. Dieses Steuerelement hat eine einfache Benutzeroberfläche und Funktionalität.This control has a simple user interface and functionality. Das Steuerelement besteht aus drei Kreisen, von denen jeweils nur ein einziger leuchten kann.The control is three circles, only one of which can be lit up at a time. Nach einiger Überlegung stellen Sie fest, die eine RadioButton bietet die Funktionalität der nur eine zeilenweise, aber die standarddarstellung der ausgewählten der RadioButton nichts sieht die Lichter an eine Ampel.After some reflection, you might realize that a RadioButton offers the functionality of only one being selected at a time, but the default appearance of the RadioButton looks nothing like the lights on a stoplight. Da die RadioButton eine Steuerelementvorlage verwendet, um seine Darstellung zu definieren ist einfach neu definieren die ControlTemplate auf die Anforderungen an das Steuerelement, und Optionsfelder Ampel darstellen lassen.Because the RadioButton uses a control template to define its appearance, it is easy to redefine the ControlTemplate to fit the requirements of the control, and use radio buttons to make your stoplight.

    Hinweis

    Obwohl eine RadioButton können eine DataTemplate, DataTemplate reicht nicht aus, in diesem Beispiel.Although a RadioButton can use a DataTemplate, a DataTemplate is not sufficient in this example. Die DataTemplate definiert die Darstellung des Inhalts eines Steuerelements.The DataTemplate defines the appearance of the content of a control. Im Fall von einem RadioButton, den Inhalt handelt, was auf der rechten Seite des Kreises angezeigt wird, der angibt, ob die RadioButton ausgewählt ist.In the case of a RadioButton, the content is whatever appears to the right of the circle that indicates whether the RadioButton is selected. Im Beispiel mit der Ampel brauchen Sie lediglich das Optionsfeld als einen Kreis darzustellen, das „aufleuchten“ kann.In the example of the stoplight, the radio button needs just be a circle that can "light up." Da die Notwendigkeit der Darstellung der Ampel sich die standarddarstellung ist das RadioButton, es ist erforderlich, neu definieren die ControlTemplate.Because the appearance requirement for the stoplight is so different than the default appearance of the RadioButton, it is necessary to redefine the ControlTemplate. Im Allgemeinen eine DataTemplate dient zum Definieren der Inhalte oder Daten, ein Steuerelement und einen ControlTemplate dient zum Definieren der Struktur eines Steuerelements ist.In general a DataTemplate is used for defining the content (or data) of a control, and a ControlTemplate is used for defining how a control is structured.

  • Trigger.Triggers. Ein Trigger können Sie das Aussehen und Verhalten eines Steuerelements dynamisch ändern, ohne ein neues Steuerelement erstellen zu müssen.A Trigger allows you to dynamically change the appearance and behavior of a control without creating a new control. Nehmen wir beispielsweise an, Sie verfügen über mehrere ListBox -Steuerelemente in Ihrer Anwendung und möchten Sie die Elemente in jedem ListBox fett und Rot sein, wenn sie ausgewählt werden.For example, suppose you have multiple ListBox controls in your application and want the items in each ListBox to be bold and red when they are selected. Möglicherweise zuerst eine Klasse erstellen, die von erbt ListBox und überschreiben die OnSelectionChanged Methode so ändern Sie die Darstellung des ausgewählten Elements ist jedoch ein besserer Ansatz besteht darin, einen Trigger hinzugefügt haben, einem Stil ein ListBoxItem , die die Darstellung der Änderungen das ausgewählte Element.Your first instinct might be to create a class that inherits from ListBox and override the OnSelectionChanged method to change the appearance of the selected item, but a better approach is to add a trigger to a style of a ListBoxItem that changes the appearance of the selected item. Mit Triggern können Sie Eigenschaftswerte bearbeiten oder basierend auf den Eigenschaftswerten Aktionen ausführen.A trigger enables you to change property values or take actions based on the value of a property. Ein EventTrigger ermöglicht es Ihnen, Aktionen, wenn ein Ereignis auftritt.An EventTrigger enables you to take actions when an event occurs.

Weitere Informationen zu Stilen, Vorlagen und Triggern finden Sie unter Erstellen von Formaten und Vorlagen.For more information about styles, templates, and triggers, see Styling and Templating.

Im Allgemeinen gilt: wenn das benötigte Steuerelement die Funktionalität eines vorhandenen Steuerelements nachmacht, aber anders aussehen soll, lohnt es sich zuerst zu überlegen, ob Sie mit einem der in diesem Abschnitt beschriebenen Verfahren die vorhandene Darstellung des Steuerelements ändern können.In general, if your control mirrors the functionality of an existing control, but you want the control to look different, you should first consider whether you can use any of the methods discussed in this section to change the existing control's appearance.

Modelle für das Erstellen von SteuerelementenModels for Control Authoring

Dank dem umfangreichen Inhaltsmodell sowie Stilen, Vorlagen und Triggern können Sie in den meisten Fällen auf das Erstellen neuer Steuerelemente verzichten.The rich content model, styles, templates, and triggers minimize the need for you to create a new control. Falls Sie jedoch ein neues Steuerelement erstellen müssen, ist es wichtig Modelle für das Erstellen von Steuerelementen in WPFWPF zu verstehen.However, if you do need to create a new control, it is important to understand the different control authoring models in WPFWPF. WPFWPF bietet drei allgemeine Modelle zum Erstellen der Steuerelemente, die jeweils verschiedene Funktionen und Flexibilitätsgrade bieten.provides three general models for creating a control, each of which provides a different set of features and level of flexibility. Die Basisklassen für die drei Modelle sind UserControl, Control, und FrameworkElement.The base classes for the three models are UserControl, Control, and FrameworkElement.

Ableiten von UserControlDeriving from UserControl

Die einfachste Möglichkeit zum Erstellen eines Steuerelements in WPFWPF ist eine Ableitung UserControl.The simplest way to create a control in WPFWPF is to derive from UserControl. Wenn Sie ein Steuerelement erstellen, erbt von UserControl, Sie die vorhandene Komponenten zum Hinzufügen der UserControl, benennen Sie die Komponenten und verweisen Sie Ereignishandler in Extensible Application Markup Language (XAML)Extensible Application Markup Language (XAML).When you build a control that inherits from UserControl, you add existing components to the UserControl, name the components, and reference event handlers in Extensible Application Markup Language (XAML)Extensible Application Markup Language (XAML). Anschließend können Sie auf die benannten Elemente verweisen und die Ereignishandler im Code definieren.You can then reference the named elements and define the event handlers in code. Dieses Entwicklungsmodell ähnelt sehr dem Modell für die Anwendungsentwicklung in WPFWPF.This development model is very similar to the model used for application development in WPFWPF.

Wenn ordnungsgemäß erstellt eine UserControl nutzen die Vorteile der umfangreiche Inhalte, Stile und Trigger.If built correctly, a UserControl can take advantage of the benefits of rich content, styles, and triggers. Allerdings, wenn das Steuerelement erbt UserControl, Personen, die das Steuerelement werden nicht in der Lage, mit einem DataTemplate oder ControlTemplate um ihre Darstellung anzupassen.However, if your control inherits from UserControl, people who use your control will not be able to use a DataTemplate or ControlTemplate to customize its appearance. Es ist erforderlich, für die Ableitung der Control Klasse oder einer ihrer abgeleiteten Klassen (außer UserControl) um ein benutzerdefiniertes Steuerelement zu erstellen, das Vorlagen unterstützt.It is necessary to derive from the Control class or one of its derived classes (other than UserControl) to create a custom control that supports templates.

Vorteile des Ableitens von UserControlBenefits of Deriving from UserControl

Erwägen Sie eine Ableitung von UserControl wenn Folgendes zutrifft:Consider deriving from UserControl if all of the following apply:

  • Sie möchten das Steuerelement auf eine ähnliche Art und Weise erstellen, wie Sie Ihre Anwendung erstellt haben.You want to build your control similarly to how you build an application.

  • Ihr Steuerelement besteht ausschließlich aus vorhandenen Komponenten.Your control consists only of existing components.

  • Es muss keine komplexe Anpassung unterstützt werden.You don't need to support complex customization.

Ableiten von ControlDeriving from Control

Ableiten von der Control -Klasse ist das Modell, das meisten der vorhandenen WPFWPF Steuerelemente.Deriving from the Control class is the model used by most of the existing WPFWPF controls. Wenn Sie ein Steuerelement erstellen, erbt die Control -Klasse, definieren Sie seine Darstellung mithilfe von Vorlagen.When you create a control that inherits from the Control class, you define its appearance by using templates. Dadurch trennen Sie die Funktionslogik von der visuellen Darstellung.By doing so, you separate the operational logic from the visual representation. Sie können auch sicherstellen, die Entkopplung von der Benutzeroberfläche und Logik mithilfe der Befehle und Bindungen anstelle von Ereignissen und vermeiden Verweise auf Elemente in der ControlTemplate wann immer möglich.You can also ensure the decoupling of the UI and logic by using commands and bindings instead of events and avoiding referencing elements in the ControlTemplate whenever possible. Wenn die Benutzeroberfläche und die Logik Ihres Steuerelements korrekt entkoppelt ist, kann ein Benutzer des Steuerelements des Steuerelements redefine ControlTemplate um ihre Darstellung anzupassen.If the UI and logic of your control are properly decoupled, a user of your control can redefine the control's ControlTemplate to customize its appearance. Obwohl das Erstellen einer benutzerdefinierten Control ist nicht so einfach wie das Erstellen von einer UserControl, eine benutzerdefinierte Control bietet die größte Flexibilität.Although building a custom Control is not as simple as building a UserControl, a custom Control provides the most flexibility.

Vorteile des Ableitens von ControlBenefits of Deriving from Control

Erwägen Sie eine Ableitung von Control anstelle der UserControl Klasse, wenn eine der folgenden Bedingungen zutrifft:Consider deriving from Control instead of using the UserControl class if any of the following apply:

  • Die Darstellung des Steuerelements über anpassbar sein sollen die ControlTemplate.You want the appearance of your control to be customizable via the ControlTemplate.

  • Das Steuerelement soll verschiedene Designs unterstützen.You want your control to support different themes.

Ableitung von FrameworkElementDeriving from FrameworkElement

Steuerelemente, die abgeleitet UserControl oder Control basieren auf dem Zusammensetzen vorhandener Elemente.Controls that derive from UserControl or Control rely upon composing existing elements. In vielen Fällen ist es sich hierbei um eine akzeptable Lösung, da jedes Objekt, das von erbt FrameworkElement kann eine ControlTemplate.For many scenarios, this is an acceptable solution, because any object that inherits from FrameworkElement can be in a ControlTemplate. Es gibt jedoch Situationen, in denen die Darstellung eines Steuerelements mehr als die Funktionalität einer einfachen Elementzusammensetzung erfordert.However, there are times when a control's appearance requires more than the functionality of simple element composition. Wenn Sie eine Komponente für diese Szenarien auf FrameworkElement ist die richtige Wahl.For these scenarios, basing a component on FrameworkElement is the right choice.

Es gibt zwei Standardmethoden zum Erstellen von FrameworkElement-basierte Komponenten: direkte Rendering und benutzerdefinierte elementzusammensetzung.There are two standard methods for building FrameworkElement-based components: direct rendering and custom element composition. Direkte Rendering beinhaltet das Überschreiben der OnRender -Methode der FrameworkElement und DrawingContext Vorgänge, die visuelle Struktur der Komponente explizit zu definieren.Direct rendering involves overriding the OnRender method of FrameworkElement and providing DrawingContext operations that explicitly define the component visuals. Dies ist die Methode ein, die Image und Border.This is the method used by Image and Border. Benutzerdefinierte elementzusammensetzung umfasst das Verwenden von Objekten des Typs Visual um die Darstellung Ihrer Komponente zu erstellen.Custom element composition involves using objects of type Visual to compose the appearance of your component. Beispiele finden Sie unter Verwenden von DrawingVisual-Objekten.For an example, see Using DrawingVisual Objects. Track ist ein Beispiel für ein Steuerelement WPFWPF , die benutzerdefinierte elementkomposition verwendet.Track is an example of a control in WPFWPF that uses custom element composition. Sie können auch direktes Rendering und benutzerdefinierte Elementzusammensetzung innerhalb eines Steuerelements kombinieren.It is also possible to mix direct rendering and custom element composition in the same control.

Vorteile der Ableitung von FrameworkElementBenefits of Deriving from FrameworkElement

Erwägen Sie eine Ableitung von FrameworkElement Wenn einer der folgenden Bedingungen zutrifft:Consider deriving from FrameworkElement if any of the following apply:

  • Sie brauchen eine genaue Steuerung der Darstellung Ihres Steuerelements, die darüber hinausgeht, was mit einer einfachen Elementzusammensetzung möglich ist.You want to have precise control over the appearance of your control beyond what is provided by simple element composition.

  • Sie möchten die Darstellung Ihres Steuerelements definieren, indem Sie Ihre eigene Renderinglogik definieren.You want to define the appearance of your control by defining your own render logic.

  • Sie möchten vorhandene Elemente in einer Weise neu zu erstellen, die Möglichkeiten hinausgehen UserControl und Control.You want to compose existing elements in novel ways that go beyond what is possible with UserControl and Control.

Grundlagen des Erstellens von SteuerelementenControl Authoring Basics

Wie bereits erläutert, ist eine der leistungsstärksten Funktionen von WPFWPF die Möglichkeit, über die Festlegung grundlegender Eigenschaften eines Steuerelements zur Bearbeitung seiner Darstellung und seines Verhaltens hinausgehen zu können, ohne ein benutzerdefiniertes Steuerelement erstellen zu müssen.As discussed earlier, one of the most powerful features of WPFWPF is the ability to go beyond setting basic properties of a control to change its appearance and behavior, yet still not needing to create a custom control. Die Funktionen für Stil, Datenbindung und Trigger werden durch das WPFWPF-Eigenschaftensystem und das WPFWPF-Ereignissystem ermöglicht.The styling, data binding, and trigger features are made possible by the WPFWPF property system and the WPFWPF event system. In den folgenden Abschnitten werden einige Verfahren beschrieben, die Sie unabhängig von dem zum Erstellen des benutzerdefinierten Steuerelements verwendeten Modell befolgen sollten, um Benutzern Ihres benutzerdefinierten Steuerelements das Zugreifen auf diese Funktionen auf die gleiche Art und Weise zu ermöglichen, wie es bei einem in WPFWPF enthaltenen Steuerelement möglich wäre.The following sections describe some practices that you should follow, regardless of the model you use to create the custom control, so that users of your custom control can use these features just as they would for a control that is included with WPFWPF.

Verwenden von AbhängigkeitseigenschaftenUse Dependency Properties

Falls es sich bei einer Eigenschaft um eine Abhängigkeitseigenschaft handelt, können Sie folgendermaßen vorgehen:When a property is a dependency property, it is possible to do the following:

  • Die Eigenschaft in einem Stil festlegen.Set the property in a style.

  • Die Eigenschaft an eine Datenquelle binden.Bind the property to a data source.

  • Eine dynamische Ressource als den Wert der Eigenschaft verwenden.Use a dynamic resource as the property's value.

  • Die Eigenschaft animieren.Animate the property.

Falls Sie möchten, dass eine Eigenschaft Ihres Steuerelements eine dieser Funktionen unterstützt, sollten Sie die Eigenschaft als eine Abhängigkeitseigenschaft implementieren.If you want a property of your control to support any of this functionality, you should implement it as a dependency property. Im folgenden Beispiel wird eine Abhängigkeitseigenschaft mit dem Namen Value wie folgt definiert:The following example defines a dependency property named Value by doing the following:

  • Definieren einer DependencyProperty Bezeichner, die mit dem Namen ValueProperty als eine public static readonly Feld.Define a DependencyProperty identifier named ValueProperty as a public static readonly field.

  • Der Eigenschaftenname im Eigenschaftensystem registriert, durch den Aufruf DependencyProperty.Register, um Folgendes anzugeben:Register the property name with the property system, by calling DependencyProperty.Register, to specify the following:

    • Den Namen der Eigenschaft.The name of the property.

    • Den Typ der Eigenschaft.The type of the property.

    • Den Typ, der die Eigenschaft besitzt.The type that owns the property.

    • Die Metadaten für die Eigenschaft.The metadata for the property. Die Metadaten enthält den Wert der Eigenschaft standardmäßig, eine CoerceValueCallback und PropertyChangedCallback.The metadata contains the property's default value, a CoerceValueCallback and a PropertyChangedCallback.

  • Eine CLRCLR Wrappereigenschaft mit dem Namen Value wird definiert. Es ist der gleiche Name, mit dem die Abhängigkeitseigenschaft registriert wurde, indem die get und set Zugriffmethoden der Eigenschaft implementiert wurden.Define a CLRCLR wrapper property named Value, which is the same name that is used to register the dependency property, by implementing the property's get and set accessors. Beachten Sie, dass die get und set Accessoren nur rufen GetValue und SetValue bzw.Note that the get and set accessors only call GetValue and SetValue respectively. Es wird empfohlen, dass die zugriffmethoden von Abhängigkeitseigenschaften keine zusätzlichen Logik enthalten, da Clients und WPFWPF umgehen können, der Accessoren und rufen GetValue und SetValue direkt.It is recommended that the accessors of dependency properties not contain additional logic because clients and WPFWPF can bypass the accessors and call GetValue and SetValue directly. Falls eine Eigenschaft z.B. an eine Datenquelle gebunden ist, wird die set-Zugriffmethode der Eigenschaft nicht aufgerufen.For example, when a property is bound to a data source, the property's set accessor is not called. Anstatt zum Hinzufügen von zusätzlichen Logik zu Get und set-Accessor, verwenden Sie die ValidateValueCallback, CoerceValueCallback, und PropertyChangedCallback Delegaten zu reagieren bzw. Überprüfen Sie den Wert ein, wenn sich diese ändern.Instead of adding additional logic to the get and set accessors, use the ValidateValueCallback, CoerceValueCallback, and PropertyChangedCallback delegates to respond to or check the value when it changes. Weitere Informationen zu diesen Rückrufen finden Sie unter Rückrufe und Validierung von Abhängigkeitseigenschaften.For more information on these callbacks, see Dependency Property Callbacks and Validation.

  • Definieren Sie eine Methode für die CoerceValueCallback mit dem Namen CoerceValue.Define a method for the CoerceValueCallback named CoerceValue. CoerceValue stellt sicher, dass Value größer oder gleich MinValue und kleiner oder gleich MaxValue ist.CoerceValue ensures that Value is greater or equal to MinValue and less than or equal to MaxValue.

  • Definieren Sie eine Methode für die PropertyChangedCallbackmit dem Namen OnValueChanged.Define a method for the PropertyChangedCallback, named OnValueChanged. OnValueChanged erstellt eine RoutedPropertyChangedEventArgs<T> -Objekt und bereitet Sie zum Auslösen der ValueChanged Routingereignis.OnValueChanged creates a RoutedPropertyChangedEventArgs<T> object and prepares to raise the ValueChanged routed event. Routingereignisse werden im nächsten Abschnitt erläutert.Routed events are discussed in the next section.

       /// <summary>
       /// Identifies the Value dependency property.
       /// </summary>
       public static readonly DependencyProperty ValueProperty =
           DependencyProperty.Register(
               "Value", typeof(decimal), typeof(NumericUpDown),
               new FrameworkPropertyMetadata(MinValue, new PropertyChangedCallback(OnValueChanged),
                                             new CoerceValueCallback(CoerceValue)));

       /// <summary>
       /// Gets or sets the value assigned to the control.
       /// </summary>
       public decimal Value
       {          
           get { return (decimal)GetValue(ValueProperty); }
           set { SetValue(ValueProperty, value); }
       }

       private static object CoerceValue(DependencyObject element, object value)
       {
           decimal newValue = (decimal)value;
           NumericUpDown control = (NumericUpDown)element;

           newValue = Math.Max(MinValue, Math.Min(MaxValue, newValue));
           
           return newValue;
       }

       private static void OnValueChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
       {
           NumericUpDown control = (NumericUpDown)obj;			

           RoutedPropertyChangedEventArgs<decimal> e = new RoutedPropertyChangedEventArgs<decimal>(
               (decimal)args.OldValue, (decimal)args.NewValue, ValueChangedEvent);
           control.OnValueChanged(e);
       }
''' <summary>
''' Identifies the Value dependency property.
''' </summary>
Public Shared ReadOnly ValueProperty As DependencyProperty = DependencyProperty.Register("Value", GetType(Decimal), GetType(NumericUpDown), New FrameworkPropertyMetadata(MinValue, New PropertyChangedCallback(AddressOf OnValueChanged), New CoerceValueCallback(AddressOf CoerceValue)))

''' <summary>
''' Gets or sets the value assigned to the control.
''' </summary>
Public Property Value() As Decimal
    Get
        Return CDec(GetValue(ValueProperty))
    End Get
    Set(ByVal value As Decimal)
        SetValue(ValueProperty, value)
    End Set
End Property

Private Shared Overloads Function CoerceValue(ByVal element As DependencyObject, ByVal value As Object) As Object
    Dim newValue As Decimal = CDec(value)
    Dim control As NumericUpDown = CType(element, NumericUpDown)

    newValue = Math.Max(MinValue, Math.Min(MaxValue, newValue))

    Return newValue
End Function

Private Shared Sub OnValueChanged(ByVal obj As DependencyObject, ByVal args As DependencyPropertyChangedEventArgs)
    Dim control As NumericUpDown = CType(obj, NumericUpDown)

    Dim e As New RoutedPropertyChangedEventArgs(Of Decimal)(CDec(args.OldValue), CDec(args.NewValue), ValueChangedEvent)
    control.OnValueChanged(e)
End Sub

Weitere Informationen finden Sie unter Benutzerdefinierte Abhängigkeitseigenschaften.For more information, see Custom Dependency Properties.

Verwenden von RoutingereignissenUse Routed Events

Ebenso wie Abhängigkeitseigenschaften, die das Konzept der CLRCLR-Eigenschaften um zusätzliche Funktionen erweitern, erweitern Routingereignisse das Konzept der CLRCLR-Standardereignisse.Just as dependency properties extend the notion of CLRCLR properties with additional functionality, routed events extend the notion of standard CLRCLR events. Beim Erstellen eines neuen WPFWPF-Steuerelements empfiehlt es sich, Ihr Ereignis als ein Routingereignis zu implementieren, da Routingereignisse folgendes Verhalten unterstützen:When you create a new WPFWPF control, it is also good practice to implement your event as a routed event because a routed event supports the following behavior:

  • Ereignisse für mehrere Steuerelemente können über ein übergeordnetes Steuerelement behandelt werden.Events can be handled on a parent of multiple controls. Falls es sich bei dem Ereignis um ein Bubbling-Ereignis handelt, kann ein einzelnes übergeordnetes Element in der Elementstruktur das Ereignis abonnieren.If an event is a bubbling event, a single parent in the element tree can subscribe to the event. Anschließend können Anwendungsentwickler mit einem Handler auf das Ereignis mehrerer Steuerelemente reagieren.Then application authors can use one handler to respond to the event of multiple controls. Z. B., wenn das Steuerelement wird von jedem Element in einer ListBox (weil es in enthalten ist ein DataTemplate), der Anwendungsentwickler kann den Ereignishandler für das-Ereignis des Steuerelements definieren, auf die ListBox.For example, if your control is a part of each item in a ListBox (because it is included in a DataTemplate), the application developer can define the event handler for your control's event on the ListBox. Beim Auftreten des Ereignisses bei einem der Steuerelemente wird der Ereignishandler aufgerufen.Whenever the event occurs on any of the controls, the event handler is called.

  • Routingereignisse können verwendet werden, eine EventSetter, damit Anwendungsentwickler den Handler eines Ereignisses innerhalb eines Stils angeben.Routed events can be used in an EventSetter, which enables application developers to specify the handler of an event within a style.

  • Routingereignisse können verwendet werden, eine EventTrigger, dies ist hilfreich zum Animieren von Eigenschaften mit XAMLXAML.Routed events can be used in an EventTrigger, which is useful for animating properties by using XAMLXAML. Weitere Informationen finden Sie unter Übersicht über Animation.For more information, see Animation Overview.

Im folgenden Beispiel wird ein Routingereignis wie folgt definiert:The following example defines a routed event by doing the following:

  • Definieren einer RoutedEvent Bezeichner, die mit dem Namen ValueChangedEvent als eine public static readonly Feld.Define a RoutedEvent identifier named ValueChangedEvent as a public static readonly field.

  • Registrieren Sie das Routingereignis durch Aufrufen der EventManager.RegisterRoutedEvent Methode.Register the routed event by calling the EventManager.RegisterRoutedEvent method. Im Beispiel gibt die folgenden Informationen an, beim Aufrufen RegisterRoutedEvent:The example specifies the following information when it calls RegisterRoutedEvent:

    • Der Name des Ereignisses lautet ValueChanged.The name of the event is ValueChanged.

    • Die Routingstrategie ist Bubble, was bedeutet, dass ein Ereignishandler für die Quelle (das Objekt, das das Ereignis auslöst) zuerst aufgerufen wird, und klicken Sie dann Ereignishandler für den übergeordneten Elementen von der Quelle nacheinander aufgerufen, beginnend mit dem am nächsten Ereignishandler übergeordnetes Element.The routing strategy is Bubble, which means that an event handler on the source (the object that raises the event) is called first, and then event handlers on the source's parent elements are called in succession, starting with the event handler on the closest parent element.

    • Der Typ des ereignishandlers ist RoutedPropertyChangedEventHandler<T>, erstellte mit einem Decimal Typ.The type of the event handler is RoutedPropertyChangedEventHandler<T>, constructed with a Decimal type.

    • NumericUpDown ist der besitzende Typ des Ereignisses.The owning type of the event is NumericUpDown.

  • Ein öffentliches Ereignis mit dem Namen ValueChanged, das die Zugriffsmethoden-Deklarationen umfasst, wird deklariert.Declare a public event named ValueChanged and includes event-accessor declarations. Das Beispiel ruft AddHandler in die add Zugriffsmethoden-Deklaration und RemoveHandler in die remove Zugriffsmethoden-Deklaration mit der WPFWPF -Ereignisdienste.The example calls AddHandler in the add accessor declaration and RemoveHandler in the remove accessor declaration to use the WPFWPF event services.

  • Eine geschützte virtuelle Methode mit dem Namen OnValueChanged, die dasValueChanged-Ereignis auslöst, wird erstellt.Create a protected, virtual method named OnValueChanged that raises the ValueChanged event.

/// <summary>
/// Identifies the ValueChanged routed event.
/// </summary>
public static readonly RoutedEvent ValueChangedEvent = EventManager.RegisterRoutedEvent(
    "ValueChanged", RoutingStrategy.Bubble, 
    typeof(RoutedPropertyChangedEventHandler<decimal>), typeof(NumericUpDown));

/// <summary>
/// Occurs when the Value property changes.
/// </summary>
public event RoutedPropertyChangedEventHandler<decimal> ValueChanged
{
    add { AddHandler(ValueChangedEvent, value); }
    remove { RemoveHandler(ValueChangedEvent, value); }
}

/// <summary>
/// Raises the ValueChanged event.
/// </summary>
/// <param name="args">Arguments associated with the ValueChanged event.</param>
protected virtual void OnValueChanged(RoutedPropertyChangedEventArgs<decimal> args)
{
    RaiseEvent(args);
}
''' <summary>
''' Identifies the ValueChanged routed event.
''' </summary>
Public Shared ReadOnly ValueChangedEvent As RoutedEvent = EventManager.RegisterRoutedEvent("ValueChanged", RoutingStrategy.Bubble, GetType(RoutedPropertyChangedEventHandler(Of Decimal)), GetType(NumericUpDown))

''' <summary>
''' Occurs when the Value property changes.
''' </summary>
Public Custom Event ValueChanged As RoutedPropertyChangedEventHandler(Of Decimal)
    AddHandler(ByVal value As RoutedPropertyChangedEventHandler(Of Decimal))
        MyBase.AddHandler(ValueChangedEvent, value)
    End AddHandler
    RemoveHandler(ByVal value As RoutedPropertyChangedEventHandler(Of Decimal))
        MyBase.RemoveHandler(ValueChangedEvent, value)
    End RemoveHandler
    RaiseEvent(ByVal sender As System.Object, ByVal e As RoutedPropertyChangedEventArgs(Of Decimal))
    End RaiseEvent
End Event

''' <summary>
''' Raises the ValueChanged event.
''' </summary>
''' <param name="args">Arguments associated with the ValueChanged event.</param>
Protected Overridable Sub OnValueChanged(ByVal args As RoutedPropertyChangedEventArgs(Of Decimal))
    MyBase.RaiseEvent(args)
End Sub

Weitere Informationen finden Sie unter Übersicht über Routingereignisse und Vorgehensweise: Erstellen eines benutzerdefinierten Routingereignisses.For more information, see Routed Events Overview and Create a Custom Routed Event.

Verwendung von BindungenUse Binding

Erwägen Sie Datenbindungen, um die Benutzeroberfläche Ihres Steuerelements von der Logik zu entkoppeln.To decouple the UI of your control from its logic, consider using data binding. Dies ist besonders wichtig, wenn Sie mit der Darstellung Ihres Steuerelements definieren eine ControlTemplate.This is particularly important if you define the appearance of your control by using a ControlTemplate. Bei der Verwendung einer Datenbindung können Sie u.U. auf die Verweise auf bestimmte Teile der Benutzeroberfläche aus dem Code verzichten.When you use data binding, you might be able to eliminate the need to reference specific parts of the UI from the code. Es ist eine gute Idee, vermeiden Sie Verweise auf Elemente in der ControlTemplate da bei der Code für Elemente, die verweist in der ControlTemplate und ControlTemplate geändert wird, wird der Verweiselement muss in der neuen aufgenommen werden ControlTemplate.It's a good idea to avoid referencing elements that are in the ControlTemplate because when the code references elements that are in the ControlTemplate and the ControlTemplate is changed, the referenced element needs to be included in the new ControlTemplate.

Das folgende Beispiel aktualisiert die TextBlock von der NumericUpDown Steuerelement, ein Name zugewiesen, und verweisen auf das Textfeld im Code mit Namen.The following example updates the TextBlock of the NumericUpDown control, assigning a name to it and referencing the textbox by name in code.

<Border BorderThickness="1" BorderBrush="Gray" Margin="2" 
        Grid.RowSpan="2" VerticalAlignment="Center" HorizontalAlignment="Stretch">
  <TextBlock Name="valueText" Width="60" TextAlignment="Right" Padding="5"/>
</Border>
private void UpdateTextBlock()
{
    valueText.Text = Value.ToString();
}
Private Sub UpdateTextBlock()
    valueText.Text = Value.ToString()
End Sub

Im folgenden Beispiel wird eine Bindung für den selben Zweck verwendet.The following example uses binding to accomplish the same thing.

<Border BorderThickness="1" BorderBrush="Gray" Margin="2" 
        Grid.RowSpan="2" VerticalAlignment="Center" HorizontalAlignment="Stretch">

    <!--Bind the TextBlock to the Value property-->
    <TextBlock 
        Width="60" TextAlignment="Right" Padding="5"
        Text="{Binding RelativeSource={RelativeSource FindAncestor, 
                       AncestorType={x:Type local:NumericUpDown}}, 
                       Path=Value}"/>

</Border>

Weitere Informationen zu Datenbindungen finden Sie unter Übersicht über Datenbindung.For more information about data binding, see Data Binding Overview.

Darstellung für DesignerDesign for Designers

Um Support für benutzerdefinierte WPF-Steuerelemente in WPF-Designer für Visual StudioWPF Designer for Visual Studio zu erhalten (z.B. bezüglich der Eigenschaftenbearbeitung mit dem Eigenschaftenfenster), befolgen Sie die folgenden Richtlinien.To receive support for custom WPF controls in the WPF-Designer für Visual StudioWPF Designer for Visual Studio (for example, property editing with the Properties window), follow these guidelines. Weitere Informationen zur Entwicklung für die WPF-DesignerWPF Designer, finden Sie unter Entwerfen von XAML in Visual Studio.For more information on developing for the WPF-DesignerWPF Designer, see Design XAML in Visual Studio.

AbhängigkeitseigenschaftenDependency Properties

Stellen Sie sicher, dass die CLRCLR, get und set-Zugriffsmethoden wie oben beschrieben inplementiert worden sind, siehe „Verwenden von Abhängigkeitseigenschaften“.Be sure to implement CLRCLR get and set accessors as described earlier, in "Use Dependency Properties." Designer können Wrapper zur Prüfung des Vorhandenseins einer Abhängigkeitseigenschaft verwenden. Diese müssen, genauso wie WPFWPF und Clients des Steuerelements, beim Abrufen oder Festlegen der Eigenschaft jedoch keine Zugriffsmethoden aufrufen.Designers may use the wrapper to detect the presence of a dependency property, but they, like WPFWPF and clients of the control, are not required to call the accessors when getting or setting the property.

Angefügte EigenschaftenAttached Properties

Angefügte Eigenschaften für benutzerdefinierte Steuerelemente sind unter Einhaltung der folgenden Richtlinien zu implementieren:You should implement attached properties on custom controls using the following guidelines:

  • Haben eine public static readonly DependencyProperty des Formulars PropertyName Property , die erstellt wurde, mithilfe der RegisterAttached Methode.Have a public static readonly DependencyProperty of the form PropertyNameProperty that was creating using the RegisterAttached method. Der Eigenschaftenname, der an übergebene RegisterAttached übereinstimmen PropertyName.The property name that is passed to RegisterAttached must match PropertyName.

  • Implementieren Sie die public static CLR-Methoden mit den Namen Set PropertyName und Get PropertyName.Implement a pair of public static CLR methods named SetPropertyName and GetPropertyName. Beide Methoden sollten eine von abgeleitete Klasse akzeptieren DependencyProperty als das erste Argument.Both methods should accept a class derived from DependencyProperty as their first argument. Die SetPropertyName-Methode akzeptiert auch ein Argument, dessen Typ mit dem registrierten Datentyp der Eigenschaft übereinstimmt.The SetPropertyName method also accepts an argument whose type matches the registered data type for the property. Die GetPropertyName-Methode sollte einen Wert zurückgeben, der den gleichen Typ aufweist.The GetPropertyName method should return a value of the same type. Falls die SetPropertyName-Methode fehlt, wird die Eigenschaft als schreibgeschützt gekennzeichnet.If the SetPropertyName method is missing, the property is marked read-only.

  • Set PropertyName und Get PropertyName direkt weiterleiten muss die GetValue und SetValue Zielabhängigkeitsobjekt Methoden für die Ziel-Abhängigkeit.Set PropertyName and GetPropertyName must route directly to the GetValue and SetValue methods on the target dependency object, respectively. Designer können auf die angefügte Eigenschaft entweder über einen Aufruf des Wrappers für die Methode zugreifen, oder indem sie das Zielabhängigkeitsobjekt direkt aufrufen.Designers may access the attached property by calling through the method wrapper or making a direct call to the target dependency object.

Weitere Informationen zu angefügten Eigenschaften finden Sie in der Übersicht über angefügte Eigenschaften.For more information on attached properties, see Attached Properties Overview.

Definieren und Verwenden von freigegebenen RessourcenDefine and Use Shared Resources

Sie können Ihr Steuerelement entweder in die Assembly Ihrer Anwendung, oder in eine separate Assembly einbinden, die in mehreren Anwendungen verwendet werden kann.You can include your control in the same assembly as your application, or you can package your control in a separate assembly that can be used in multiple applications. Der Großteil der in diesem Thema erläuterten Informationen gilt unabhängig von der von Ihnen verwendeten Methode.For the most part, the information discussed in this topic applies regardless of the method you use. Ein wesentlicher Unterschied ist dennoch zu beachten.There is one difference worth noting, however. Falls Sie ein Steuerelement in die Assembly einer Anwendung einbinden, können Sie der App.xaml-Datei globale Ressourcen hinzufügen.When you put a control in the same assembly as an application, you are free to add global resources to the App.xaml file. Aber eine Assembly, die nur Steuerelemente enthält, verfügt nicht über eine Application Objekt zugeordnet, sodass eine "App.xaml" nicht verfügbar ist.But an assembly that contains only controls does not have an Application object associated with it, so an App.xaml file is not available.

Wenn eine Anwendung nach einer Ressource sucht,wird auf drei Ebenen in der folgenden Reihenfolge gesucht:When an application looks for a resource, it looks at three levels in the following order:

  1. Die Elementebene.The element level.

    Das System beginnt mit dem Element, das auf die Ressource verweist, und sucht anschließend die Ressourcen des logischen übergeordneten Elements durch. Dieser Schritt wir wiederholt, bis das Stammelement erreicht ist.The system starts with the element that references the resource and then searches resources of the logical parent and so forth until the root element is reached.

  2. Die Anwendungsebene.The application level.

    Ressourcen, die von definiert die Application Objekt.Resources defined by the Application object.

  3. Die Designebene.The theme level.

    Ressourcenverzeichnisse werden auf der Designebene in einem Themes-Unterordner gespeichert.Theme-level dictionaries are stored in a subfolder named Themes. Die Dateien im Themes-Ordner entsprechen den Designs.The files in the Themes folder correspond to themes. Dort könnten Sie beispielsweise Aero.NormalColor.xaml, Luna.NormalColor.xaml, Royale.NormalColor.xaml, etc. finden.For example, you might have Aero.NormalColor.xaml, Luna.NormalColor.xaml, Royale.NormalColor.xaml, and so on. Möglicherweise ist auch eine Datei mit dem Namen generic.xaml enthalten.You can also have a file named generic.xaml. Bei einer Suche nach einer Ressource auf der Designebene wird zunächst in der designspezifischen Datei und dann in der Datei generic.xaml gesucht.When the system looks for a resource at the themes level, it first looks for it in the theme-specific file and then looks for it in generic.xaml.

Falls Ihr Steuerelement in einer anderen Assembly als die Anwendung liegt, müssen Sie Ihre globale Ressourcen auf die Elementen- oder Designebene umspeichern.When your control is in an assembly that is separate from the application, you must put your global resources at the element level or at the theme level. Beide Methoden haben ihre Vorteile.Both methods have their advantages.

Definieren von Ressourcen auf der ElementebeneDefining Resources at the Element Level

Sie können freigegebene Ressourcen auf der Elementebene definieren, indem Sie ein benutzerdefiniertes Ressourcenverzeichnis erstellen und es mit dem Ressourcenverzeichnis Ihres Steuerelements zusammenführen.You can define shared resources at the element level by creating a custom resource dictionary and merging it with your control’s resource dictionary. Falls Sie sich für diese Methode entscheiden, können Sie die Ressourcendatei beliebig benennen und sie im Ordner speichern, wo Ihre Steuerelemente liegen.When you use this method, you can name your resource file anything you want, and it can be in the same folder as your controls. Für Ressourcen auf der Elementebene können ebenso einfache Zeichenfolgen als Schlüssel verwendet werden.Resources at the element level can also use simple strings as keys. Das folgende Beispiel erstellt eine LinearGradientBrush Ressourcendatei mit dem Namen Dictionary1.XAML angelegt.The following example creates a LinearGradientBrush resource file named Dictionary1.xaml.

<ResourceDictionary 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <LinearGradientBrush 
    x:Key="myBrush"  
    StartPoint="0,0" EndPoint="1,1">
    <GradientStop Color="Red" Offset="0.25" />
    <GradientStop Color="Blue" Offset="0.75" />
  </LinearGradientBrush>
  
</ResourceDictionary>

Nachdem Sie das Ressourcenverzeichnis definiert haben, müssen Sie es mit dem Ressourcenverzeichnis des Steuerelements zusammenführen.Once you have defined your dictionary, you need to merge it with your control's resource dictionary. Hierzu können Sie XAMLXAML oder Code verwenden.You can do this by using XAMLXAML or code.

Im folgenden Beispiel wird ein Ressourcenverzeichnis mit XAMLXAML zusammengeführt.The following example merges a resource dictionary by using XAMLXAML.

<UserControl.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="Dictionary1.xaml"/>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</UserControl.Resources>

Der Nachteil dieses Ansatzes besteht darin, die eine ResourceDictionary Objekt erstellt, wenn Sie darauf verweisen.The disadvantage to this approach is that a ResourceDictionary object is created each time you reference it. Z. B. Wenn Sie 10 benutzerdefinierte Steuerelemente in der Bibliothek und die freigegebenen Ressourcenverzeichnisse für jedes Steuerelement mit XAML zusammenführen, Sie erstellen 10 identische ResourceDictionary Objekte.For example, if you have 10 custom controls in your library and merge the shared resource dictionaries for each control by using XAML, you create 10 identical ResourceDictionary objects. Sie können dies verhindern, erstellen Sie eine statische Klasse, die die Ressourcen im Code zusammenführt, und gibt das resultierende ResourceDictionary.You can avoid this by creating a static class that merges the resources in code and returns the resulting ResourceDictionary.

Das folgende Beispiel erstellt eine Klasse, die eine freigegebene gibt ResourceDictionary.The following example creates a class that returns a shared ResourceDictionary.

internal static class SharedDictionaryManager
{
    internal static ResourceDictionary SharedDictionary
    {
        get
        {
            if (_sharedDictionary == null)
            {
                System.Uri resourceLocater =
                    new System.Uri("/ElementResourcesCustomControlLibrary;component/Dictionary1.xaml", 
                                    System.UriKind.Relative);

                _sharedDictionary = 
                    (ResourceDictionary)Application.LoadComponent(resourceLocater);
            }

            return _sharedDictionary;
        }
    }

    private static ResourceDictionary _sharedDictionary;
}

Im folgenden Beispiel wird die freigegebene Ressource mit den Ressourcen eines benutzerdefinierten Steuerelements im Konstruktor des Steuerelements zusammengeführt, bevor sie InitializeComponent aufruft.The following example merges the shared resource with the resources of a custom control in the control's constructor before it calls InitializeComponent. Da die SharedDictionaryManager.SharedDictionary ist eine statische Eigenschaft, die ResourceDictionary wird nur einmal erstellt.Because the SharedDictionaryManager.SharedDictionary is a static property, the ResourceDictionary is created only once. Da das Ressourcenverzeichnis vor dem Aufruf von InitializeComponent zusammengeführt worden ist, kann das Steuerelement auf die Ressourcen in seiner XAMLXAML-Datei zugreifen.Because the resource dictionary was merged before InitializeComponent was called, the resources are available to the control in its XAMLXAML file.

public NumericUpDown()
{
    this.Resources.MergedDictionaries.Add(SharedDictionaryManager.SharedDictionary);
    InitializeComponent();

}

Definieren von Ressourcen auf der DesignebeneDefining Resources at the Theme Level

Mit WPFWPF können Sie Ressourcen für verschiedene Windows-Designs erstellen.WPFWPF enables you to create resources for different Windows themes. Als Autor des Steuerelements können Sie eine Ressource für ein bestimmtes Design definieren, um die Darstellung Ihres Steuerelements an das jeweils verwendete Design anzupassen.As a control author, you can define a resource for a specific theme to change your control's appearance depending on what theme is in use. Z. B. die Darstellung des eine Button Design (das Standarddesign für Windows 2000) auf der Windows-klassisch unterscheidet sich von einer Button im Windows Luna-Design (das Standarddesign für Windows XP) da die Button verwendet ein anderes ControlTemplate für jedes Design.For example, the appearance of a Button in the Windows Classic theme (the default theme for Windows 2000) differs from a Button in the Windows Luna theme (the default theme for Windows XP) because the Button uses a different ControlTemplate for each theme.

Designspezifische Ressourcen werden in einem Ressourcenverzeichnis mit dem entsprechenden Dateinamen gespeichert.Resources that are specific to a theme are kept in a resource dictionary with a specific file name. Diese Dateien müssen sich im Themes-Verzeichnis befinden, einem Unterordner des Ordners, in dem sich das Steuerelement befindet.These files must be in a folder named Themes that is a subfolder of the folder that contains the control. In der folgenden Tabelle sind die Ressourcenverzeichnisdateien sowie die den einzelnen Dateien zugeordneten Designs aufgelistet:The following table lists the resource dictionary files and the theme that is associated with each file:

Name der RessourcenverzeichnisdateiResource dictionary file name Windows-DesignWindows theme
Classic.xaml Klassische Windows 9x/2000-Darstellung unter Windows XPClassic Windows 9x/2000 look on Windows XP
Luna.NormalColor.xaml Blaues Standard-Design unter Windows XPDefault blue theme on Windows XP
Luna.Homestead.xaml Olivgrünes Design unter Windows XPOlive theme on Windows XP
Luna.Metallic.xaml Silbernes Design unter Windows XPSilver theme on Windows XP
Royale.NormalColor.xaml Standarddesign von Windows XP Media Center EditionDefault theme on Windows XP Media Center Edition
Aero.NormalColor.xaml Standarddesign unter Windows VistaDefault theme on Windows Vista

Sie müssen nicht für jedes Design eine Ressource definieren.You do not need to define a resource for every theme. Wenn eine Ressource nicht für ein bestimmtes Design definiert ist, durchsucht das Steuerelement Classic.xaml nach der Ressource.If a resource is not defined for a specific theme, then the control checks Classic.xaml for the resource. Falls die Ressource weder in der Datei, die dem aktuellen Design entspricht, noch in Classic.xaml definiert ist, verwendet das Steuerelement die generische Ressource, die sich im Ressourcenverzeichnis mit dem Namen generic.xaml befindet.If the resource is not defined in the file that corresponds to the current theme or in Classic.xaml, the control uses the generic resource, which is in a resource dictionary file named generic.xaml. Die generic.xaml-Datei befindet sich im gleichen Ordner mit den designspezifischen Ressourcenverzeichnisdateien.The generic.xaml file is located in the same folder as the theme-specific resource dictionary files. Obwohl generic.xaml keinem bestimmten Windows-Design entspricht, ist es dennoch ein Ressourcenverzeichnis auf der Designebene.Although generic.xaml does not correspond to a specific Windows theme, it is still a theme-level dictionary.

Beispiel für benutzerdefiniertes NumericUpDown-Steuerelement mit Unterstützung von Designs und Benutzeroberflächenautomatisierung enthält zwei Ressourcenverzeichnisse für das NumericUpDown-Steuerelement: jeweils in den Dateien generic.xaml und Luna.NormalColor.xaml.NumericUpDown Custom Control with Theme and UI Automation Support Sample contains two resource dictionaries for the NumericUpDown control: one is in generic.xaml and one is in Luna.NormalColor.xaml. Um den Unterschied zwischen den beiden Steuerelementvorlagen zu sehen, starten Sie die Anwendung, und wechseln Sie zwischen dem silbernen Design für Windows XP und einem anderen Design.You can run the application and switch between the Silver theme in Windows XP and another theme to see the difference between the two control templates. (Unter Windows Vista können Sie die Datei Luna.NormalColor.xaml in Aero.NormalColor.xaml umbenennen und zwischen zwei Designs, z.B. Windows - klassisch und Standarddesign für Windows Vista, wechseln.)(If you are running Windows Vista, you can rename Luna.NormalColor.xaml to Aero.NormalColor.xaml and switch between two themes, such as Windows Classic and the default theme for Windows Vista.)

Wenn Sie Einfügen ein ControlTemplate in einer der designspezifischen ressourcenverzeichnisdateien, müssen Sie einen statischen Konstruktor für Ihr Steuerelement und rufen erstellen die OverrideMetadata(Type, PropertyMetadata) Methode für die DefaultStyleKey, wie im folgenden Beispiel gezeigt.When you put a ControlTemplate in any of the theme-specific resource dictionary files, you must create a static constructor for your control and call the OverrideMetadata(Type, PropertyMetadata) method on the DefaultStyleKey, as shown in the following example.

static NumericUpDown()
{
    DefaultStyleKeyProperty.OverrideMetadata(typeof(NumericUpDown),
               new FrameworkPropertyMetadata(typeof(NumericUpDown)));
}
Shared Sub New()
    DefaultStyleKeyProperty.OverrideMetadata(GetType(NumericUpDown), New FrameworkPropertyMetadata(GetType(NumericUpDown)))
End Sub
Definieren und Angeben von Schlüsseln für DesignressourcenDefining and Referencing Keys for Theme Resources

Wenn Sie eine Ressource auf der Elementebene definieren, können Sie ihr als Schlüssel eine Zeichenfolge zuweisen und über diese Zeichenfolge auf sie zugreifen.When you define a resource at the element level, you can assign a string as its key and access the resource via the string. Wenn Sie eine Ressource auf der Designebene definieren, müssen Sie verwenden eine ComponentResourceKey als Schlüssel.When you define a resource at the theme level, you must use a ComponentResourceKey as the key. Im folgenden Beispiel wird eine Ressource in generic.xaml definiert.The following example defines a resource in generic.xaml.

<LinearGradientBrush 
     x:Key="{ComponentResourceKey TypeInTargetAssembly={x:Type local:Painter}, 
                                  ResourceId=MyEllipseBrush}"  
                                  StartPoint="0,0" EndPoint="1,0">
    <GradientStop Color="Blue" Offset="0" />
    <GradientStop Color="Red" Offset="0.5" />
    <GradientStop Color="Green" Offset="1"/>
</LinearGradientBrush>

Im folgende Beispiel wird auf die Ressource durch Angabe der ComponentResourceKey als Schlüssel.The following example references the resource by specifying the ComponentResourceKey as the key.

<RepeatButton 
    Grid.Column="1" Grid.Row="0"
    Background="{StaticResource {ComponentResourceKey 
                        TypeInTargetAssembly={x:Type local:NumericUpDown}, 
                        ResourceId=ButtonBrush}}">
    Up
</RepeatButton>
<RepeatButton 
    Grid.Column="1" Grid.Row="1"
    Background="{StaticResource {ComponentResourceKey 
                    TypeInTargetAssembly={x:Type local:NumericUpDown}, 
                    ResourceId=ButtonBrush}}">
    Down
 </RepeatButton>
Angeben des Speicherorts von DesignressourcenSpecifying the Location of Theme Resources

Um die Ressourcen für ein Steuerelement zu finden, muss die Hostinganwendung über die Information verfügen, dass die Assembly Ressourcen enthält, die steuerelementenspezifisch sind.To find the resources for a control, the hosting application needs to know that the assembly contains control-specific resources. Sie erreichen, die durch das Hinzufügen der ThemeInfoAttribute auf die Assembly, die das Steuerelement enthält.You can accomplish that by adding the ThemeInfoAttribute to the assembly that contains the control. Die ThemeInfoAttribute verfügt über eine GenericDictionaryLocation -Eigenschaft, die den Speicherort generischer Ressourcen angibt und ein ThemeDictionaryLocation -Eigenschaft, die den Speicherort der designspezifischen Ressourcen angibt.The ThemeInfoAttribute has a GenericDictionaryLocation property that specifies the location of generic resources, and a ThemeDictionaryLocation property that specifies the location of the theme-specific resources.

Im folgenden Beispiel wird die GenericDictionaryLocation und ThemeDictionaryLocation Eigenschaften SourceAssembly, um anzugeben, dass die generischen und designspezifischen Ressourcen in der gleichen Assembly wie das Steuerelement befinden.The following example sets the GenericDictionaryLocation and ThemeDictionaryLocation properties to SourceAssembly, to specify that the generic and theme-specific resources are in the same assembly as the control.

[assembly: ThemeInfo(ResourceDictionaryLocation.SourceAssembly, 
           ResourceDictionaryLocation.SourceAssembly)]
<Assembly: ThemeInfo(ResourceDictionaryLocation.SourceAssembly, ResourceDictionaryLocation.SourceAssembly)>

Siehe auchSee also