INotifyPropertyChanged e proprietà statiche

Sto legando a me stesso in nodi su un semplice problema. Ho una classe che implementa INotifyPropertyChanged. Alcune delle proprietà di istanza’ getter utilizzare le proprietà statiche e quindi i loro valori possono cambiare, se la proprietà statica modifiche? Ecco un esempio semplificato.

class ExampleClass : INotifyPropertyChanged
{

    private static int _MinimumLength = 5;
    public static int MinimumLength
    {
        get
        {
            return _MinimumLength;
        }
        set
        {
            if (_MinimumLength != value)
            {
                _MinimumLength = value;
                //WHAT GOES HERE
            }
        }
    }

    private int _length = -1;
    public int length
    {
        get
        {
            return (_length > _MinimumLength) ? _length : _MinimumLength;
        }
        set
        {
            var oldValue = (_length > _MinimumLength) ? _length : _MinimumLength;
            if (_length != value)
            {
                _length = value;
                var newValue = (_length > _MinimumLength) ? _length : _MinimumLength;
                if (newValue != oldValue)
                {
                    OnPropertyChanged("length");
                }
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

}

Chiaramente se la proprietà statica MinimumLength modifiche quindi ogni istanza della proprietà length possono anche cambiare. Ma come dovrebbe essere la proprietà statica segnalare il possibile modificare le istanze? È possibile chiamare OnPropertyChanged dal momento che non è statico.

Ho potuto tenere un elenco a livello di classe di tutte le istanze e chiamare un metodo di ciascuno, ma in qualche modo che si sente come eccessivo. O potrei tirare le proprietà statiche in una classe singleton, ma logicamente vivono a livello di classe. C’è un modello consolidato per questo o devo pensare a questo in modo diverso?

InformationsquelleAutor dumbledad | 2013-01-30

 

3 Replies
  1. 13

    Se siete inclini a sostenere che il design quindi vorrei andare con una soluzione come la seguente:

    public static int MinimumLength
    {
        get { return _MinimumLength; }
        set
        {
            if (_MinimumLength != value)
            {
                _MinimumLength = value;
                OnGlobalPropertyChanged("MinimumLength");
            }
        }
    }
    static event PropertyChangedEventHandler GlobalPropertyChanged = delegate { };
    static void OnGlobalPropertyChanged(string propertyName)
    {
        GlobalPropertyChanged(
            typeof (ExampleClass), 
            new PropertyChangedEventArgs(propertyName));
    }
    public ExampleClass()
    {
        //This should use a weak event handler instead of normal handler
        GlobalPropertyChanged += this.HandleGlobalPropertyChanged;
    }
    void HandleGlobalPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        switch (e.PropertyName)
        {
            case "MinimumLength":
                if (length > MinimumLength)
                    length = MinimumLength;
                break;
        }
    }

    Questo è più o meno equivalente al mantenimento di un elenco di istanze, ma trovo più gestibile e più chiara. Inoltre, si ha realmente bisogno di utilizzare un debole gestore di eventi di strategia, in caso contrario, le istanze non saranno immondizia raccolti perché saranno sempre associati con l’evento statico che agisce come un GC radice.

    Si può leggere di più debole e gestori di eventi nel seguente blog post (che sono stati scritti da me, perché io sono di parte):

    .NETTO Deboli i Gestori di Eventi – Parte I

    .NETTO Deboli i Gestori di Eventi – Parte I

    In una nota non correlato il codice è attualmente cottura cambiato proprietà quando, in realtà, il valore della proprietà non cambia. Per esempio:

    1. Set MinimumLength a 5;
    2. Impostare la lunghezza di 10; (caso di incendi in quanto le modifiche del valore di default 0 a 5)
    3. Impostare la lunghezza di 11; (caso di incendio, ma non dovrebbe, in quanto la durata è ancora 5)
    • E +1 (se potessi votare di nuovo) per il link al tuo post sul blog, mi chiedevo che cosa si intende dire di standard di gestione degli eventi e la raccolta dei rifiuti. Grazie anche per individuare la falla nel mio codice! Ho modificato per tener conto del bug che hai individuato.
    • Come WPF utilizzare se la soluzione?! non siamo di attuazione INotifyPropertyChanged! Io sto affrontando il problema adesso.
  2. 6

    Si potrebbe utilizzare la tecnica citata in Associazione proprietà statica e l’attuazione di INotifyPropertyChanged ma anche sollevare una notifica contro la “lunghezza”, ad esempio,

    class ExampleClass : INotifyPropertyChanged
    {
        private static int _MinimumLength = 5;
    
        public int MinimumLength
        {
            get
            {
                return _MinimumLength;
            }
            set
            {
                if (_MinimumLength != value)
                {
                    _MinimumLength = value;
    
                    OnPropertyChanged("MinimumLength");
                    OnPropertyChanged("length");
                }
            }
        }
        ...
    }
    • Che è intelligente, grazie Phil. Per far funzionare tutto ciò che ha voluto impostare il MinimumLength avrebbe bisogno di un’istanza di se. Dovrò pensare che attraverso.
    • Il problema qui è che solo notificare l’istanza per cui è impostata MinimumLength. Non la notifica a tutte le altre istanze.
    • Un buon punto. Oh beh, io non posso pensare di disordinato soluzioni che coinvolgono statico dizionario dei casi, ma non si può andare lì.
  3. 0

    ero di fronte allo stesso problema. Ecco la soluzione che ho messo in atto.

    public class ZoomDataVm : ModelBase
    {
        public ZoomDataVm()
        {
            //initialise the zoom
        }
    
        private double _zoomLevel;
        public double ZoomLevel
        {
            get { return _zoomLevel; }
            set
            {
                if (_zoomLevel != value)
                {
                    _zoomLevel = value;
                    RaisePropertyChanged(() => ZoomLevel);
                    //
                    //persist zoom info
                }
            }
        }
    }
    
    public class ZoomVm : ModelBase
    {
        public static ZoomDataVm _instance;
    
        static ZoomVm()
        {
            _instance = new ZoomDataVm();
        }
    
        public ZoomDataVm Instance
        {
            get { return _instance; }
        }
    }

    Poi io la uso in XAML che

    <StackPanel>
        <StackPanel.Resources>
            <screenControls:ZoomVm x:Key="ZoomVm" />
        </StackPanel.Resources>
        <TextBlock Text="{Binding ElementName=uiScaleSliderContainer, Path=Tag}" Foreground="White" Margin="0,0,20,0" />
        <Control Name="uiScaleSliderContainer"
            Margin="0,0,0,0"
            VerticalAlignment="Center"
            HorizontalAlignment="Left"
            Tag="{Binding Source={StaticResource ZoomVm}, Path=Instance.ZoomLevel}">
            <Control.Template>
                <ControlTemplate>
                    <Slider Orientation="Horizontal"
                        Width="400"
                        x:Name="uiScaleSlider"
                        ToolTip="Zoom"
                        Value="{Binding ElementName=uiScaleSliderContainer, Path=Tag}"
                        Minimum="0.1"
                        Maximum="2"
                        TickFrequency="0.1"
                        IsSnapToTickEnabled="True">
                    </Slider>
                </ControlTemplate>
            </Control.Template>
        </Control>
    </StackPanel>

Lascia un commento