wpf
Afhankelijkheidseigenschappen
Zoeken…
Invoering
Afhankelijkheidseigenschappen zijn een type eigenschap dat een CLR-eigenschap uitbreidt. Terwijl een CLR-eigenschap rechtstreeks van een lid van uw klasse wordt gelezen, wordt een eigenschap Dependency dynamisch omgezet bij het aanroepen van de methode GetValue () die uw object verkrijgt via overerving van de basisklasse DependencyObject.
In deze sectie worden afhankelijkheidseigenschappen onderverdeeld en wordt het gebruik ervan zowel conceptueel als via codevoorbeelden uitgelegd.
Syntaxis
- DependencyProperty.Register (tekenreeksnaam, Type propertyType, Type ownerType)
- DependencyProperty.Register (tekenreeksnaam, Type propertyType, Type ownerType, PropertyMetadata typeMetadata)
- DependencyProperty.Register (tekenreeksnaam, Type propertyType, Type ownerType, PropertyMetadata typeMetadata, ValidateValueCallback validateValueCallback)
- DependencyProperty.RegisterAttached (tekenreeksnaam, Type propertyType, Type ownerType)
- DependencyProperty.RegisterAttached (tekenreeksnaam, Type propertyType, Type ownerType, PropertyMetadata typeMetadata)
- DependencyProperty.RegisterAttached (tekenreeksnaam, Type propertyType, Type ownerType, PropertyMetadata typeMetadata, ValidateValueCallback validateValueCallback)
- DependencyProperty.RegisterReadOnly (tekenreeksnaam, Type propertyType, Type ownerType, PropertyMetadata typeMetadata)
- DependencyProperty.RegisterReadOnly (tekenreeksnaam, Type propertyType, Type ownerType, PropertyMetadata typeMetadata, ValidateValueCallback validateValueCallback)
- DependencyProperty.RegisterAttachedReadOnly (tekenreeksnaam, Type propertyType, Type ownerType, PropertyMetadata typeMetadata)
- DependencyProperty.RegisterAttachedReadOnly (stringnaam, Type propertyType, Type ownerType, PropertyMetadata typeMetadata, ValidateValueCallback validateValueCallback)
parameters
Parameter | Details |
---|---|
naam | De String van de naam van de eigenschap |
Eigendom type | Het Type eigenschap, bijvoorbeeld typeof(int) |
ownerType | Het Type van de klasse waarin de eigenschap wordt gedefinieerd, bijvoorbeeld typeof(MyControl) of typeof(MyAttachedProperties) . |
typeMetadata | Exemplaar van System.Windows.PropertyMetadata (of een van de subklassen) die standaardwaarden definieert, door eigenschappen gewijzigde callbacks, FrameworkPropertyMetadata maakt het mogelijk om System.Windows.Data.BindingMode.TwoWay zoals System.Windows.Data.BindingMode.TwoWay te definiëren. |
validateValueCallback | Aangepaste callback die true retourneert als de nieuwe waarde van de eigenschap geldig is, anders false. |
Standaard afhankelijkheidseigenschappen
Wanneer te gebruiken
Vrijwel alle WPF-besturingselementen maken intensief gebruik van afhankelijkheidseigenschappen. Een afhankelijkheidseigenschap maakt het gebruik van veel WPF-functies mogelijk die niet mogelijk zijn met standaard CLR-eigenschappen alleen, inclusief maar niet beperkt tot ondersteuning voor stijlen, animaties, gegevensbinding, waardevererving en wijzigingsmeldingen.
De eigenschap TextBox.Text
is een eenvoudig voorbeeld van waar een standaardafhankelijkheidseigenschap nodig is. Hier zou gegevensbinding niet mogelijk zijn als Text
een standaard CLR-eigenschap was.
<TextBox Text="{Binding FirstName}" />
Hoe te definiëren
Afhankelijkheidseigenschappen kunnen alleen worden gedefinieerd in klassen die zijn afgeleid van DependencyObject
, zoals FrameworkElement
, Control
, etc.
Een van de snelste manieren om een standaard afhankelijkheid eigenschap te maken zonder dat de syntax te onthouden is om de "propdp" fragment door te typen gebruiken propdp
en vervolgens op Tab te drukken. Er wordt een codefragment ingevoegd dat vervolgens kan worden aangepast aan uw behoeften:
public class MyControl : Control
{
public int MyProperty
{
get { return (int)GetValue(MyPropertyProperty); }
set { SetValue(MyPropertyProperty, value); }
}
// Using a DependencyProperty as the backing store for MyProperty.
// This enables animation, styling, binding, etc...
public static readonly DependencyProperty MyPropertyProperty =
DependencyProperty.Register("MyProperty", typeof(int), typeof(MyControl),
new PropertyMetadata(0));
}
Je moet Tab door de verschillende delen van de code snippet om de noodzakelijke veranderingen, met inbegrip van het bijwerken van de eigenschap naam, het type woning, met klasse-type, en de standaardwaarde te maken.
Belangrijke conventies
Hier volgen enkele belangrijke conventies / regels:
Maak een CLR-eigenschap voor de afhankelijkheidseigenschap. Deze eigenschap wordt gebruikt in de code achter uw object of door andere consumenten. Het zou
GetValue
enSetValue
moeten oproepen, zodat consumenten dat niet hoeven te doen.Geef de afhankelijkheidseigenschap de juiste naam. Het veld
DependencyProperty
moet alleenpublic static readonly
. Het moet een naam hebben die overeenkomt met de CLR-eigenschapsnaam en eindigt op "Eigenschap", bijv.Text
enTextProperty
.Voeg geen extra logica toe aan de setter van de CLR-eigenschap. Het afhankelijkheidseigenschappensysteem (en XAML specifiek) maakt geen gebruik van de CLR-eigenschap. Als u een actie wilt uitvoeren wanneer de waarde van de eigenschap verandert, moet u terugbellen via
PropertyMetadata
:public static readonly DependencyProperty MyPropertyProperty = DependencyProperty.Register("MyProperty", typeof(int), typeof(MyControl), new PropertyMetadata(0, MyPropertyChangedHandler)); private static void MyPropertyChangedHandler(DependencyObject sender, DependencyPropertyChangedEventArgs args) { // Use args.OldValue and args.NewValue here as needed. // sender is the object whose property changed. // Some unboxing required. }
Bindende modus
Om de noodzaak voor het opgeven van Mode=TwoWay
in bindingen (vergelijkbaar met het gedrag van TextBox.Text
) te TextBox.Text
, werkt u de code bij om FrameworkPropertyMetadata
te gebruiken in plaats van PropertyMetadata
en geeft u de juiste vlag op:
public static readonly DependencyProperty MyPropertyProperty =
DependencyProperty.Register("MyProperty", typeof(int), typeof(MyControl),
new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
Bijgevoegde afhankelijkheidseigenschappen
Wanneer te gebruiken
Een bijgevoegde eigenschap is een afhankelijkheidseigenschap die kan worden toegepast op een DependencyObject
om het gedrag van verschillende besturingselementen of services die op de hoogte zijn van het bestaan van de eigenschap te verbeteren.
Enkele use cases voor bijgevoegde eigenschappen zijn:
- Een ouderelement door zijn kinderen laten itereren en op een bepaalde manier op de kinderen reageren. Het besturingselement
Grid
gebruikt bijvoorbeeld de gekoppelde eigenschappenGrid.Row
,Grid.Column
,Grid.RowSpan
enGrid.ColumnSpan
om elementen in rijen en kolommen te rangschikken. - Visuals toevoegen aan bestaande besturingselementen met aangepaste sjablonen, bijvoorbeeld watermerken toevoegen aan lege tekstvakken in de hele app zonder
TextBox
te hoevenTextBox
. - Het verstrekken van een generieke service of functie voor sommige of alle bestaande besturingselementen, bijvoorbeeld
ToolTipService
ofFocusManager
. Dit worden gewoonlijk aangehecht gedrag genoemd . - Wanneer overerving naar beneden de visuele boom vereist is, bijvoorbeeld vergelijkbaar met het gedrag van
DataContext
.
Dit toont verder wat er gebeurt in de Grid
use case:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Content="Your Name:" />
<TextBox Grid.Column="1" Text="{Binding FirstName}" />
</Grid>
Grid.Column
is geen eigenschap die voorkomt op Label
of TextBox
. In plaats daarvan doorzoekt het Grid
de onderliggende elementen en rangschikt ze volgens de waarden van de gekoppelde eigenschappen.
Hoe te definiëren
We zullen Grid
voor dit voorbeeld blijven gebruiken. De definitie van Grid.Column
wordt hieronder weergegeven, maar de DependencyPropertyChangedEventHandler
is voor de beknoptheid uitgesloten.
public static readonly DependencyProperty RowProperty =
DependencyProperty.RegisterAttached("Row", typeof(int), typeof(Grid),
new FrameworkPropertyMetadata(0, ...));
public static void SetRow(UIElement element, int value)
{
if (element == null)
throw new ArgumentNullException("element");
element.SetValue(RowProperty, value);
}
public static int GetRow(UIElement element)
{
if (element == null)
throw new ArgumentNullException("element");
return ((int)element.GetValue(RowProperty));
}
Omdat de gekoppelde eigenschappen kunnen worden gekoppeld aan een breed scala aan items, kunnen ze niet worden geïmplementeerd als CLR-eigenschappen. In plaats daarvan wordt een paar statische methoden geïntroduceerd.
Daarom kunnen gekoppelde eigenschappen, in tegenstelling tot standaardafhankelijkheidseigenschappen, ook worden gedefinieerd in klassen die niet zijn afgeleid van DependencyObject
.
Dezelfde naamgevingsconventies die van toepassing zijn op reguliere afhankelijkheidseigenschappen zijn ook hier van toepassing: de afhankelijkheidseigenschap RowProperty
heeft de overeenkomstige methoden GetRow
en SetRow
.
Voorbehoud
Zoals gedocumenteerd op MSDN :
Hoewel overerving van eigenschapswaarde lijkt te werken voor niet-gekoppelde afhankelijkheidseigenschappen, is het overervingsgedrag voor een niet-gekoppelde eigenschap door bepaalde elementgrenzen in de runtime-structuur niet gedefinieerd. Gebruik altijd RegisterAttached om eigenschappen te registreren waar u Inherits opgeeft in de metagegevens.
Alleen-lezen afhankelijkheidseigenschappen
Wanneer te gebruiken
Een alleen-lezen afhankelijkheidseigenschap is vergelijkbaar met een normale afhankelijkheidseigenschap, maar is zodanig gestructureerd dat de waarde niet van buiten de controle kan worden ingesteld. Dit werkt goed als u een eigenschap hebt die puur informatief is voor consumenten, bijvoorbeeld IsMouseOver
of IsKeyboardFocusWithin
.
Hoe te definiëren
Net als standaard afhankelijkheidseigenschappen moet een alleen-lezen afhankelijkheidseigenschap worden gedefinieerd voor een klasse die is afgeleid van DependencyObject
.
public class MyControl : Control
{
private static readonly DependencyPropertyKey MyPropertyPropertyKey =
DependencyProperty.RegisterReadOnly("MyProperty", typeof(int), typeof(MyControl),
new FrameworkPropertyMetadata(0));
public static readonly DependencyProperty MyPropertyProperty = MyPropertyPropertyKey.DependencyProperty;
public int MyProperty
{
get { return (int)GetValue(MyPropertyProperty); }
private set { SetValue(MyPropertyPropertyKey, value); }
}
}
Dezelfde conventies die van toepassing zijn op reguliere afhankelijkheidseigenschappen zijn ook hier van toepassing, maar met twee belangrijke verschillen:
- De
DependencyProperty
is afkomstig van eenprivate
DependencyPropertyKey
. - De CLR-eigenschappeninsteller is
protected
ofprivate
plaats vanpublic
.
Merk op dat de setter MyPropertyPropertyKey
en niet MyPropertyProperty
aan de SetValue
methode. Omdat de eigenschap alleen-lezen was gedefinieerd, moet elke poging om SetValue
op de eigenschap te gebruiken, worden gebruikt met overbelasting die DependencyPropertyKey
ontvangt; anders wordt een InvalidOperationException
gegenereerd.