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:

  1. Maak een CLR-eigenschap voor de afhankelijkheidseigenschap. Deze eigenschap wordt gebruikt in de code achter uw object of door andere consumenten. Het zou GetValue en SetValue moeten oproepen, zodat consumenten dat niet hoeven te doen.

  2. Geef de afhankelijkheidseigenschap de juiste naam. Het veld DependencyProperty moet alleen public static readonly . Het moet een naam hebben die overeenkomt met de CLR-eigenschapsnaam en eindigt op "Eigenschap", bijv. Text en TextProperty .

  3. 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:

  1. Een ouderelement door zijn kinderen laten itereren en op een bepaalde manier op de kinderen reageren. Het besturingselement Grid gebruikt bijvoorbeeld de gekoppelde eigenschappen Grid.Row , Grid.Column , Grid.RowSpan en Grid.ColumnSpan om elementen in rijen en kolommen te rangschikken.
  2. Visuals toevoegen aan bestaande besturingselementen met aangepaste sjablonen, bijvoorbeeld watermerken toevoegen aan lege tekstvakken in de hele app zonder TextBox te hoeven TextBox .
  3. Het verstrekken van een generieke service of functie voor sommige of alle bestaande besturingselementen, bijvoorbeeld ToolTipService of FocusManager . Dit worden gewoonlijk aangehecht gedrag genoemd .
  4. 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:

  1. De DependencyProperty is afkomstig van een private DependencyPropertyKey .
  2. De CLR-eigenschappeninsteller is protected of private plaats van public .

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.



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow