Ü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. Die Content-Eigenschaft eines Button ist beispielsweise vom Typ Object, sodass theoretisch alles auf einem Buttonangezeigt werden kann.For example, the content property of a Button is of type Object, so theoretically anything can be displayed on a Button. Wenn eine Schaltfläche ein Bild und Text anzeigen soll, können Sie ein Bild und ein TextBlock StackPanel einem hinzufügen Content und das StackPanel der-Eigenschaft zuweisen.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 zum Inhalts Modell für Button und andere Inhalts Modelle in WPFWPFfinden Sie unter WPF-Inhalts Modell.For more information about the content model for Button and other content models in WPFWPF, see WPF Content Model.

  • Stile.Styles. Eine Style ist eine Auflistung 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. Angenommen, Sie möchten, dass alle TextBlock Steuerelemente eine rote, Arial Schriftart mit einem Schrift Grad von 14 haben.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. Dann wird TextBlock jedes, das Sie der Anwendung hinzufügen, dasselbe Aussehen.Then every TextBlock that you add to your application will have the same appearance.

  • Datenvorlagen.Data Templates. Mit DataTemplate einem können Sie anpassen, wie Daten auf einem-Steuerelement angezeigt werden.A DataTemplate enables you to customize how data is displayed on a control. So DataTemplate kann z. b. verwendet werden, um anzugeben, wie Daten in ListBoxeinem angezeigt werden.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 kann ein DataTemplate Benutzeroberflächen Elemente enthalten, die Ihnen einen großen Flexibilität in benutzerdefinierten Benutzeroberflächen bieten.In addition to customizing the appearance of data, a DataTemplate can include UI elements, which gives you a lot of flexibility in custom UIs. Beispielsweise können Sie mit DataTemplateeinem eine ComboBox erstellen, in der 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 WPFWPF in verwenden ControlTemplate ein, um die Struktur und die Darstellung des Steuer Elements zu definieren, die die Darstellung eines-Steuer Elements von der Funktionalität des-Steuer Elements trennt.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 Steuer Elements drastisch ändern, indem Sie dessen ControlTemplateneu definieren.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 Reflektion können Sie feststellen, RadioButton dass ein-Wert die Funktionalität von nur einem gleichzeitig ausgewählten bietet, aber die Standarddarstellung RadioButton des sieht nicht so aus, wie die Lichter auf einem stoplight.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 eine Steuerelement Vorlage ControlTemplate verwendet,umdieDarstellungzudefinieren,isteseinfach,das-Elementsozudefinieren,dassesdenAnforderungendes-SteuerElementsentspricht,undmithilfevonOptionsFelderndasstoplightzumachen.RadioButtonBecause 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 eine DataTemplateverwenden DataTemplate kann, ist in diesem Beispiel nicht ausreichend. RadioButtonAlthough a RadioButton can use a DataTemplate, a DataTemplate is not sufficient in this example. DataTemplate Definiert die Darstellung des Inhalts eines-Steuer Elements.The DataTemplate defines the appearance of the content of a control. Im Fall eines RadioButtonwird der Inhalt auf der rechten Seite des Kreises angezeigt, der angibt, RadioButton ob 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 sich die Darstellungs Anforderung für das Ampel von der Standarddarstellung von RadioButtonunterscheidet, muss die ControlTemplateneu definiert werden.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 wird DataTemplate eine zum Definieren des Inhalts (oder der Daten) eines-Steuer Elements verwendet, ControlTemplate und ein wird verwendet, um zu definieren, wie ein Steuerelement strukturiert 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. Mit Trigger einem können Sie die Darstellung und das Verhalten eines Steuer Elements 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. Angenommen, Sie verfügen über mehrere ListBox Steuerelemente in der Anwendung und möchten, dass die Elemente in den einzelnen ListBox Steuerelementen Fett und rot sind, 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. Der erste Instinkt besteht darin, eine Klasse zu erstellen, die von ListBox erbt und OnSelectionChanged die-Methode überschreibt, um die Darstellung des ausgewählten Elements zu ändern. ein besserer Ansatz ist jedoch das Hinzufügen eines ListBoxItem -Auslösers zu einem Stil von, der die Darstellung von 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. Mit EventTrigger können Sie Aktionen ausführen, 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, Controlund 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 Steuer Elements WPFWPF in ist das ableiten UserControlvon von.The simplest way to create a control in WPFWPF is to derive from UserControl. Wenn Sie ein Steuerelement erstellen, das von UserControlerbt, fügen Sie vorhandene Komponenten UserControlhinzu, benennen Sie die Komponenten, und verweisen Sie auf Extensible Application Markup Language (XAML)Extensible Application Markup Language (XAML)Ereignishandler in.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 Sie ordnungsgemäß erstellt UserControl wurde, kann ein die Vorteile von umfangreichen Inhalten, Stilen und Triggern nutzen.If built correctly, a UserControl can take advantage of the benefits of rich content, styles, and triggers. Wenn das Steuerelement jedoch von UserControlerbt, können Personen, die Ihr Steuerelement verwenden, keine DataTemplate oder ControlTemplate verwenden, um die 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 notwendig, von der Control -Klasse oder einer ihrer abgeleiteten Klassen ( UserControlmit Ausnahme von) abzuleiten, 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

Sie können ableiten UserControl von ableiten, 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

Die Ableitung von Control der-Klasse ist das Modell, das von den WPFWPF meisten vorhandenen Steuerelementen verwendet wird.Deriving from the Control class is the model used by most of the existing WPFWPF controls. Wenn Sie ein Steuerelement erstellen, das von der Control -Klasse erbt, 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, dass die Benutzeroberfläche und die Logik entkoppelt werden, indem Sie anstelle von Ereignissen Befehle und Bindungen verwenden ControlTemplate und Verweise auf Elemente in der vermeiden, wenn dies möglich ist.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 des Steuer Elements ordnungsgemäß entkoppelt sind, kann ein Benutzer des Steuer Elements ControlTemplate das Steuerelement neu definieren, um seine 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 Entwickeln eines Control benutzerdefinierten nicht so einfach ist wie UserControldas Entwickeln eines Control , bietet ein benutzerdefiniertes 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

Wenn eine der Control folgenden Bedingungen zutrifft, UserControl empfiehlt es sich, von abzuleiten, anstatt die-Klasse zu verwenden:Consider deriving from Control instead of using the UserControl class if any of the following apply:

  • Sie möchten, dass die Darstellung des Steuer Elements über den ControlTemplateanpassbar ist.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 UserControl von Control abgeleitet werden oder auf das Verfassen vorhandener Elemente basieren.Controls that derive from UserControl or Control rely upon composing existing elements. In vielen Szenarios ist dies eine akzeptable Lösung, da jedes Objekt, das von FrameworkElement erbt, in einem ControlTemplatevorhanden sein kann.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. Für diese Szenarios ist die Grundlage einer FrameworkElement Komponente auf die richtige Wahl.For these scenarios, basing a component on FrameworkElement is the right choice.

Es gibt zwei Standardmethoden für die FrameworkElementErstellung von-basierten Komponenten: direktes Rendering und benutzerdefinierte Element Komposition.There are two standard methods for building FrameworkElement-based components: direct rendering and custom element composition. Das direkte Rendering umfasst das OnRender überschreiben FrameworkElement der- DrawingContext Methode von und das Bereitstellen von Vorgängen, die explizit die visuellen KomponentenDirect rendering involves overriding the OnRender method of FrameworkElement and providing DrawingContext operations that explicitly define the component visuals. Dies ist die Methode, die Image von Borderund verwendet wird.This is the method used by Image and Border. Die benutzerdefinierte Element Komposition umfasst die Verwendung Visual von Objekten des Typs, um das Erscheinungsbild der 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. Trackist ein Beispiel für ein Steuerelement WPFWPF in, das die benutzerdefinierte Element Komposition 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

Sie können ableiten FrameworkElement , wenn eine 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 auf neuartige Weise verfassen, die über die Möglichkeiten von UserControl und Controlhinausgehen.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 Sie DependencyProperty einen Bezeichner mit public dem ValueProperty static Namenreadonly als Feld.Define a DependencyProperty identifier named ValueProperty as a public static readonly field.

  • Registrieren Sie den Eigenschaftsnamen beim Eigenschaften System, indem DependencyProperty.RegisterSie aufrufen, um Folgendes anzugeben:Register the property name with the property system, by calling DependencyProperty.Register, to specify the following:

    • Der Name 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 enthalten den Standardwert der Eigenschaft, a CoerceValueCallback PropertyChangedCallbackund.The metadata contains the property's default value, a CoerceValueCallback and a PropertyChangedCallback.

  • Definieren Sie eine CLR-Wrapper ValueEigenschaft mit dem Namen, die dem Namen entspricht, der verwendet wird, um die Abhängigkeits Eigenschaft zu get registrieren set , indem Sie die-und-Accessoren der Eigenschaft implementieren.Define a CLR 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, get dass set die-und- GetValue SetValue Accessoren nur bzw. aufzurufen.Note that the get and set accessors only call GetValue and SetValue respectively. Es wird empfohlen, dass die Accessoren von Abhängigkeits Eigenschaften keine zusätzliche Logik enthalten, WPFWPF da Clients und die Accessoren umgehen GetValue und SetValue direkt abrufen können.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 den Get-und Set-Accessoren zusätzliche Logik hinzuzufügen, verwenden ValidateValueCallbackSie CoerceValueCallbackdie Delegaten, und PropertyChangedCallback , um auf den Wert zu reagieren oder den Wert zu überprüfen, wenn er sich ändert.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 CoerceValueCallback das CoerceValuebenannte.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 PropertyChangedCallbackden mit OnValueChangeddem Namen.Define a method for the PropertyChangedCallback, named OnValueChanged. OnValueChangederstellt ein RoutedPropertyChangedEventArgs<T> -Objekt und bereitet darauf vor ValueChanged , das-Routing Ereignis zu erhöhen.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ängigkeits Eigenschaften das Konzept von CLR-Eigenschaften mit zusätzlicher Funktionalität erweitern, erweitern Routing Ereignisse das Konzept von CLR-Standard Ereignissen.Just as dependency properties extend the notion of CLR properties with additional functionality, routed events extend the notion of standard CLR 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. Wenn das Steuerelement z. b. ein Teil der einzelnen Elemente in ListBox einer ist (da es in einer DataTemplateenthalten ist), kann der Anwendungsentwickler den Ereignishandler für das ListBox-Ereignis des Steuer Elements im definieren.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.

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

  • Routing Ereignisse können in EventTriggerverwendet werden, was zum Animieren von Eigenschaften mithilfe XAMLXAMLvon nützlich ist.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 Sie RoutedEvent einen Bezeichner mit public dem ValueChangedEvent static Namenreadonly als Feld.Define a RoutedEvent identifier named ValueChangedEvent as a public static readonly field.

  • Registrieren Sie das-Routing Ereignis, EventManager.RegisterRoutedEvent indem Sie die-Methode aufrufen.Register the routed event by calling the EventManager.RegisterRoutedEvent method. Das Beispiel gibt die folgenden Informationen an, wenn RegisterRoutedEventaufgerufen wird:The example specifies the following information when it calls RegisterRoutedEvent:

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

    • Die Routing Strategie ist Bubble. Dies bedeutet, dass ein Ereignishandler für die Quelle (das Objekt, das das Ereignis auslöst) zuerst aufgerufen wird. Anschließend werden die Ereignishandler für die übergeordneten Elemente der Quelle nacheinander aufgerufen, beginnend mit dem Ereignishandler am nächstgelegenen ü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 Ereignis Handlers ist RoutedPropertyChangedEventHandler<T>, erstellt 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. Im Beispiel wird AddHandler in der add Accessordeklaration RemoveHandler und in remove der Accessordeklaration aufgerufen WPFWPF , um die Ereignis Dienste zu verwenden.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 die Darstellung des Steuer Elements mithilfe eines ControlTemplatedefinieren.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 empfiehlt sich, ControlTemplate Verweise auf Elemente in zu vermeiden, denn wenn der Code auf Elemente verweist, die sich in der ControlTemplate befinden und die ControlTemplate geändert wird, muss das Element, auf das verwiesen wird, in ControlTemplatedas neue eingeschlossen werden.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.

Im folgenden Beispiel wird die TextBlock NumericUpDown des-Steuer Elements aktualisiert, und es wird ein Name zugewiesen, und im Code wird anhand des Namens auf das Textfeld verwiesen.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 zum entwickeln für finden Sie WPF-DesignerWPF Designerunter 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 get CLR set und Accessoren wie zuvor beschrieben in "Abhängigkeits Eigenschaften verwenden" implementiert werden.Be sure to implement CLR 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:

  • Verwenden Sie public eine static readonly RegisterAttachedderForm PropertyName,Property die mithilfe der-Methode erstellt wurde. DependencyPropertyHave a public static readonly DependencyProperty of the form PropertyNameProperty that was creating using the RegisterAttached method. Der an übergebenen Eigenschaften Name muss RegisterAttached mit propertyNameidentisch sein.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 DependencyProperty abgeleitete Klasse als das erste Argument akzeptieren.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.

  • SetPropertyName und Get propertyName müssen direkt an die GetValue -Methode und die- SetValue Methode für das Ziel Abhängigkeits Objekt weiterleiten.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. Einer Assembly, die nur Steuerelemente enthält, ist jedoch Application kein Objekt zugeordnet, sodass keine app. XAML-Datei 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 durch Application das-Objekt definiert werden.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. Im folgenden Beispiel wird eine LinearGradientBrush Ressourcen Datei mit dem Namen Dictionary1. XAML erstellt.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, dass ResourceDictionary jedes Mal, wenn Sie darauf verweisen, ein-Objekt erstellt wird.The disadvantage to this approach is that a ResourceDictionary object is created each time you reference it. Wenn Sie z. b. über 10 benutzerdefinierte Steuerelemente in der Bibliothek verfügen und die freigegebenen Ressourcen Wörterbücher für jedes Steuerelement mithilfe von XAML zusammenführen, erstellen Sie 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. Dies können Sie vermeiden, indem Sie eine statische Klasse erstellen, die die Ressourcen im Code zusammenfasst ResourceDictionaryund die resultierende zurückgibt.You can avoid this by creating a static class that merges the resources in code and returns the resulting ResourceDictionary.

Im folgenden Beispiel wird eine-Klasse erstellt, die ResourceDictionaryeine freigegebene zurückgibt.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 eine statische Eigenschaft ResourceDictionary ist,wirdnureinmalerstellt.SharedDictionaryManager.SharedDictionaryBecause 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. Beispielsweise unter Button scheidet sich die Darstellung eines im klassischen Windows-Design (das Standarddesign für Windows 2000) von einem Button im Windows-Luna-Design (Standarddesign für Button Windows XP), da 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.

Das C# benutzerdefinierte Steuerelement oder Visual Basic NumericUpDown-Steuerelement mit Design-und Benutzeroberflächenautomatisierungs NumericUpDown -Unterstützung enthält zwei Ressourcen Wörterbücher für das-Steuerelement: eines in Generic. XAML und das andere in Luna. NormalColor. XAML.The C# or Visual Basic NumericUpDown custom control with theme and UI automation support sample contains two resource dictionaries for the NumericUpDown control: one is in generic.xaml, and the other is in Luna.NormalColor.xaml.

Wenn Sie ControlTemplate in einer der Design spezifischen Ressourcenverzeichnis Dateien platzieren, müssen Sie für das Steuerelement einen statischen Konstruktor erstellen und die OverrideMetadata(Type, PropertyMetadata) -Methode für den DefaultStyleKeyaufzurufen, 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 Design Ebene definieren, müssen Sie einen ComponentResourceKey als Schlüssel verwenden.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 folgenden Beispiel wird auf die Ressource verwiesen, ComponentResourceKey indem als Schlüssel angegeben wird.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. Dies erreichen Sie, indem Sie der ThemeInfoAttribute Assembly, die das Steuerelement enthält, hinzufügen.You can accomplish that by adding the ThemeInfoAttribute to the assembly that contains the control. Der ThemeInfoAttribute verfügt über GenericDictionaryLocation eine-Eigenschaft, die den Speicherort der generischen ThemeDictionaryLocation Ressourcen angibt, und eine-Eigenschaft, die den Speicherort der Design spezifischen 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 werden die GenericDictionaryLocation - ThemeDictionaryLocation Eigenschaft und SourceAssemblydie-Eigenschaft auf festgelegt, um anzugeben, dass sich die generischen und Design spezifischen Ressourcen in derselben 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