Benutzer:MovGP0/WPF/Dependency Object

aus Wikipedia, der freien Enzyklopädie
Zur Navigation springen Zur Suche springen
   MovGP0        Über mich        Hilfen        Artikel        Weblinks        Literatur        Zitate        Notizen        Programmierung        MSCert        Physik      


Dependency Object

[Bearbeiten | Quelltext bearbeiten]

WPF Property Requirements

[Bearbeiten | Quelltext bearbeiten]
  • Change Notifications
  • Default Values
  • Type Coercion
  • Data Binding
  • Attached Properties
  • Validation
  • Inheritance
  • Styling
  • Designer Support
  • Animation
  • etc.

Dependency Property

[Bearbeiten | Quelltext bearbeiten]
public sealed class Person : DependencyObject
{
    public static readonly DependencyProperty = 
        DependencyProperty.Register(nameof(Name), typeof(string), typeof(Person), 
            new UIPropertyMetadata(string.Empty));

    // helper that will not be used by WPF
    // may not contain additional logic 
    public string Name
    {
        get { return (string) GetValue(NameProperty); }
        set { SetValue(NameProperty, value); }
    }
}

with Change Notification

[Bearbeiten | Quelltext bearbeiten]
public sealed class Person : DependencyObject
{
    public static readonly DependencyProperty = 
        DependencyProperty.Register(nameof(Name), typeof(string), typeof(Person), 
            new UIPropertyMetadata(string.Empty, OnNameChanged));

    // every time the value changes 
    private static void OnNameChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
    {
        var target = (Person)source;
        var name = (string)e.NewValue; // e.OldValue, e.Property 
        target.OnNameChanged(name);
    }

    private void OnNameChanged(string Name)
    {
        // ...
    }

    public string Name
    {
        get { return (string) GetValue(NameProperty); }
        set { SetValue(NameProperty, value); }
    }
}

Attached Properties

[Bearbeiten | Quelltext bearbeiten]
<MyElement>
    <ChildElement MyElement.MyProperty="foo" />
</MyElement>
public sealed MyElement : DependencyObject // ie. Control
{
    public static readonly DependencyProperty MyPropertyProperty = 
        DependencyProperty.RegisterAttached("MyProperty", typeof(string), typeof(MyElement), 
            new UIPropertyMetadata(string.Empty));

    public static string GetMyProperty(DependencyObject obj)
    {
        return (string)obj.GetValue(MyPropertyProperty);
    }

    public static void SetMyProperty(DependencyObject obj, string value)
    {
        obj.SetValue(MyPropertyProperty, value);
    }
}

Inherited Properties

[Bearbeiten | Quelltext bearbeiten]
  • Properties that child elements get from their container
  • do not use for callbacks, because callback will be called on every child element
public sealed class Person : DependencyObject
{
    public static readonly DependencyProperty = 
        DependencyProperty.Register(nameof(Name), typeof(string), typeof(Person), 
            new UIPropertyMetadata(string.Empty, FrameworkPropertyMetadata.Inherits));

    public string Name
    {
        get { return (string) GetValue(NameProperty); }
        set { SetValue(NameProperty, value); }
    }
}

Readonly Properties

[Bearbeiten | Quelltext bearbeiten]
  • not setable
  • no data binding
  • no validation
  • no animation
  • no inheritance
  • used for state determination
private static readonly DependencyPropertyKey NamePropertyKey = 
    DependencyProperty.RegisterReadOnly(nameof(Name), typeof(MyControl), new PropertyMetadata(false));

private static readonly DependencyProperty NameProperty = 
    DependencyPropertyKey.DependencyProperty;

public string Name
{
    get { return (string)GetValue(NameProperty); }
}

// change value behind read-only property
public void ChangeName(string newName)
{
    SetValue(DependencyPropertyKey, newName); 
}

Collection Properties

[Bearbeiten | Quelltext bearbeiten]

Command Properties

[Bearbeiten | Quelltext bearbeiten]
User Control
<Grid>
    <Grid.DataContext>
        <local:MyControlViewModel />
    </Grid.DataContext>
    <Button Command="{Binding Command}" />
</Grid>
public class MyControl : UserControl
{
    public static readonly DependencyProperty CommandProperty = 
        DependencyProperty.Register(nameof(Command), typeof(ICommand), typeof(UserControl));

    public ICommand Command
    {
        get { return (ICommand)GetValue(CommandProperty);  }
        set { SetValue(CommandProperty, value); }
    }

    private void InvokeCommand()
    {
        Command?.Execute();
    }
}
Usage
public class MyViewModel
{
    public ICommand ViewModelCommand { get; } = new DelegateCommand(OnViewModelCommandExecute);

    private void OnViewModelCommandExecute()
    {
        // ...
    }
}
<UserControls:UserControl Command="{Binding ViewModelCommand}" />

Property Metadata

[Bearbeiten | Quelltext bearbeiten]
  • PropertyMetadata
    • Default Value (Singleton)
    • PropertyChangedCallback (react to value change)
    • CoerceValueCallback (intercept and change the value for this control without changing the value)
  • FrameworkPropertyMetadata
    • only inside a FrameworkElement (ie. Window, UserControl)
    • FrameworkPropertyMetadataOptions
      • change or disable default binding mode
      • define inherited property
      • define if a change of this property affects arrangement, measurement or rendering of this control

Observing DependencyProperties[1]

[Bearbeiten | Quelltext bearbeiten]
    public static class DependencyObjectExtensions
    {
        public static IObservable<EventArgs> Observe<T>(this T component, DependencyProperty dependencyProperty)
            where T:DependencyObject
        {
            return Observable.Create<EventArgs>(observer =>
            {
                EventHandler update = (sender, args) => observer.OnNext(args);
                var property = DependencyPropertyDescriptor.FromProperty(dependencyProperty, typeof(T));
                property.AddValueChanged(component, update);
                return Disposable.Create(() => property.RemoveValueChanged(component, update));
            });
        }
    }

    this.Observe(SomeProperty).Subscribe(args => ...);
  1. Listen to changes of dependency property. In: StackOverflow. Abgerufen am 14. November 2016.