[WPF] Mutable objects en DependencyProperties

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Mnstrspeed
  • Registratie: Oktober 2007
  • Laatst online: 14:49
Ik heb ergens in mijn (fictieve) project een mutable class die een event triggert als er iets verandert:

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public delegate void ChangedEventHandler(object sender, EventArgs e);

public class Configuration
{
    private string name;
    public string Name
    {
        set 
        { 
            this.name = value; 
            OnChanged(); 
        }
        get { return this.name; }
    }

    public event ChangedEventHandler Changed;

    protected void OnChanged()
    {
        if (this.Changed != null)
            this.Changed(this, EventArgs.Empty);
    }
}

En verderop ergens in mijn WPF-applicatie een UserControl met een DependencyProperty:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class MyControl : UserControl
{
    public static readonly DependencyProperty ConfigurationProperty =
        DependencyProperty.Register("Configuration", typeof(Configuration), 
        typeof(MyControl), new FrameworkPropertyMetadata(null,
            FrameworkPropertyMetadataOptions.AffectsRender));
    
    public Configuration Configuration
    {
        get { return GetValue(ConfigurationProperty) as Configuration; }
        set { SetValue(ConfigurationProperty, value); }
    }

    protected override void OnRender(DrawingContext drawingContext)
    {
        // Render something with data from Configuration
    }
}

Dit had geweldig gewerkt als 'Configuration' immutable was geweest en ik iedere keer een nieuwe waarde aan de DependencyProperty had toegewezen, maar helaas. Ik zoek een manier om de DependencyProperty op het 'Changed' event uit 'Configuration' te laten reageren (een nieuwe render laten triggeren, volgens FrameworkPropertyMetadataOptions.AffectsRender). Nou kan ik zelf natuurlijk een PropertyChangedCallback aan de DependencyProperty hangen en me handmatig aanmelden voor 'Configuration.Changed' en dan een InvalidateRender() aanroepen bij iedere trigger, maar dat lijkt me geen mooie oplossing.

Is dit voorzien in WPF?

Ehhh wat?


Acties:
  • 0 Henk 'm!

  • Niemand_Anders
  • Registratie: Juli 2006
  • Laatst online: 09-07-2024

Niemand_Anders

Dat was ik niet..

Je moet de interface INotifyPropertyChanged implementeren voor de 'Configuration' class. De XAML DataBinding abonneert zich dan automatisch op dit event (PropertyChanged) en zal veranderingen direct doorvoeren op de GUI.

Het lijkt erop dat je nogal wat kennis mist van WPF. Aangezien XAML en databinding ook worden gebruikt in Silverlight en Windows Phone is het misschien geen slecht idee om een boek als 'Pro WPF' aan te schaffen. WPF is heel erg krachtig en het is jammer als maar een klein deel gebruikt zal worden.

If it isn't broken, fix it until it is..


Acties:
  • 0 Henk 'm!

  • BM
  • Registratie: September 2001
  • Laatst online: 18:29

BM

Moderator Spielerij
Of een NameChanged event, dat wil ook werken, maar is lang zo flexibel niet dat INotifyPropertyChanged :)

Xbox
Even the dark has a silver lining | I'm all you can imagine times infinity, times three


Acties:
  • 0 Henk 'm!

  • Niemand_Anders
  • Registratie: Juli 2006
  • Laatst online: 09-07-2024

Niemand_Anders

Dat was ik niet..

Ik ga er vanuit dat Configuration meer properties zal bevatten dan alleen een naam. Was trouwens ook niet helemaal zeker of NameChanged standaard WPF was of een onderdeel van Caliburn..

If it isn't broken, fix it until it is..


Acties:
  • 0 Henk 'm!

  • Mnstrspeed
  • Registratie: Oktober 2007
  • Laatst online: 14:49
'Configuration' is maar een voorbeeld om niet een heel stuk code hier buiten context neer te hoeven gooien :) En inderdaad, ik heb nog niet veel met WPF gedaan; ik werk momenteel aan een hobby project waar ik nu een (simpele) GUI aan wil hangen en om WinForms er nou weer bij te pakken leek me ook zowat...

Ik heb INotifyPropertyChanged op Configuration geimplementeerd, maar niemand abboneert zich erop (PropertyChanged event is altijd null):

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Configuration : INotifyPropertyChanged
{
    private string name; 
    public string Name 
    { 
        set  
        {  
            this.name = value;
            this.OnPropertyChanged("Name"); 
        } 
        get { return this.name; } 
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string propertyName)
    {
        if (this.PropertyChanged != null) // altijd null
        {
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

Mis ik toevallig een speciaal vlaggetje voor mijn DependencyProperty om 'm automagisch te laten abonneren?

Ehhh wat?


Acties:
  • 0 Henk 'm!

  • Snake
  • Registratie: Juli 2005
  • Laatst online: 07-03-2024

Snake

Los Angeles, CA, USA

Bind iets wel op Configuration.Name?

Going for adventure, lots of sun and a convertible! | GMT-8


Acties:
  • 0 Henk 'm!

  • Mnstrspeed
  • Registratie: Oktober 2007
  • Laatst online: 14:49
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        myControl.Configuration = new Configuration() { Name = "Foo" };
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        myControl.Configuration.Name = "Bar";
    }
}

Ehhh wat?


Acties:
  • 0 Henk 'm!

  • Snake
  • Registratie: Juli 2005
  • Laatst online: 07-03-2024

Snake

Los Angeles, CA, USA

Ik bedoel in XAML :*

Going for adventure, lots of sun and a convertible! | GMT-8


Acties:
  • 0 Henk 'm!

  • Mnstrspeed
  • Registratie: Oktober 2007
  • Laatst online: 14:49
In m'n MainWindow.xaml defineer ik alleen de control:

XML:
1
2
3
4
5
6
7
8
9
10
<Window x:Class="DependencyPropertyTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:DependencyPropertyTest"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel Orientation="Vertical">
        <local:MyControl x:Name="myControl" Width="200" Height="200" />
        <Button Content="Don't click me" Click="Button_Click" />
    </StackPanel>
</Window>

Ehhh wat?


Acties:
  • 0 Henk 'm!

  • Snake
  • Registratie: Juli 2005
  • Laatst online: 07-03-2024

Snake

Los Angeles, CA, USA

En in de MyControl? Hoe ziet daar de XAML er van uit?

Going for adventure, lots of sun and a convertible! | GMT-8


Acties:
  • 0 Henk 'm!

  • Mnstrspeed
  • Registratie: Oktober 2007
  • Laatst online: 14:49
Die heeft geen XAML: ik render handmatig door OnRender te overriden. Reden hiervoor is, dat in mijn eigenlijke project de control te gecompliceerd is om helemaal in XAML te maken (denk aan een grafiekje of iets in die richting).

Ehhh wat?

Pagina: 1