Domanda

Ho bisogno di sapere ciò che la procedura è per fare una dipendenza-proprietà di sola scrittura. Posso vedere che la classe DependencyProperty non dispone di un metodo speciale "Register" per le proprietà di sola scrittura, ma non ho idea se il metodo RegisterAttached può applicare a quello che sto cercando di fare.

Questa struttura deve essere una dipendenza-di proprietà, piuttosto che una semplice proprietà CLR. Internamente, la mia classe richiede un PropertyChangedCallback su questa proprietà, al fine di rimanere stabile.

Lo so che la dipendenza-proprietà di sola scrittura possono essere creati, in quanto si afferma chiaramente in:
Pro C # 2008 e la piattaforma nofollow noreferrer .NET 3.5 , Pagina 1061 .
Tuttavia, questo è l'unico posto dove posso trovare anche "proprietà di dipendenza" e "scrivere solo" sulla stessa pagina. E questo autore a quanto pare non ha pensato è stato necessario in realtà mostrare al lettore la procedura per qualcosa di diverso da una lettura-scrittura dipendenza-proprietà di base. Naturalmente, questo libro potrebbe essere un carico di BS - ma questo libro sembra piuttosto standard, quindi penso che sia una scommessa abbastanza sicuro che l'autore è corretta. Presumo la mancanza di informazioni su Internet deriva dal fatto che nessuno in genere bisogno di fare una proprietà come questa.

So che suona molto discutibile a voler fare la propria dipendenza-proprietà di sola scrittura. Vi assicuro che ha senso in cui lo voglio. La mia classe ha una proprietà il cui valore è utile solo per l'impostazione oggetto. Se un altro oggetto dovesse richiedere il valore di questa proprietà in seguito, non sarebbe in grado di dare un senso razionale di valore senza conoscere il contesto originale del regolatore.

Questa proprietà non è destinato ad essere utilizzato a scopo informativo. Lasciando oggetti esterni tentano di utilizzare il valore della proprietà in questo modo è problematico, pericoloso, e un rischio per la sicurezza. Quindi credo che il miglior design è quello di vietare le operazioni di lettura su questa proprietà. Chiunque utilizzi la mia classe troverà che sono costretti a utilizzare la classe il modo in cui è stato concepito, che lavorerà molto meglio e più pulito alla fine.

È stato utile?

Soluzione

Non è possibile, questo sembra essere di progettazione. Anche se posso capire il tuo approccio al libro citato e sono in alcun modo mettere in discussione la sua qualità, mi piacerebbe ancora Presumo che questo sia una sorta di copia & incolla o problema simile. Qui è il mio ragionamento:

WPF codice di sistema di proprietà

la progettazione del sistema di proprietà WPF

  • Più importante, 'L'attuale implementazione WPF del suo processore XAML è intrinsecamente proprietà di dipendenza a conoscenza. Il processore WPF XAML utilizza metodi sistema immobili in proprietà di dipendenza durante il caricamento attributi XAML e lavorazione binari che sono proprietà di dipendenza. Questo esclude in modo efficace gli involucri di proprietà. ', vedere XAML Caricamento e Dipendenza proprietà .
  • Il più importante, 'proprietà di dipendenza dovrebbe generalmente essere considerati proprietà pubbliche. La natura del (WPF) sistema di proprietà di Windows Presentation Foundation impedisce la capacità di fare le garanzie di sicurezza su un valore di proprietà di dipendenza. ', vedere Dipendenza Sicurezza Proprietà .

In particolare questi ultimi due punti stanno delineando il vincolo di progettazione, che i valori delle proprietà di dipendenza sono sempre accessibili tramite GetValue () / SetValue () , non importa se i loro involucri CLR sono l'accesso limitato o disponibili a tutti, con la sola eccezione della specificatamente rappresentato il Read-Only proprietà di dipendenza .

Di conseguenza, come Jeffs risposta implica già, basta rimuovere il getter per esempio in realtà non impedire a chiunque l'accesso alla proprietà avviene mediante GetValue () , anche se questo può almeno 'ridurre lo spazio dei nomi immediatamente esposta di una classe personalizzata' . L'utilità di tale soluzione semantica di rendere il propevalore rty un po 'meno visibile / accessibile e il valore recuperato intrinsecamente inutile per i clienti, come suggerito dal Jeff dipende dalla vostra particolare scenario, naturalmente.

Altri suggerimenti

Interessante, questo è sicuramente uno scenario di rara, sarei interessato a sapere di più in quello che abilita.

Vuoi prendere in considerazione l'idea di fornire un valore non valido (come null) per legge attraverso il legame o GetValue, mentre solo non avendo un getter CLR?

Utilizzare un DependencyProperty privato per memorizzare il valore "reale" che ti interessano, o solo una variabile membro privato.

Nella proprietà modificata richiamata, ripristinare sempre il valore al valore originale, mentre la memorizzazione via il nuovo valore impostato.

trascorro la maggior parte del mio tempo a fare lo sviluppo di controllo Silverlight ora, quindi questa proprietà funziona in WPF e Silverlight-terre, e non usa coercian o qualcosa di divertente come quella. Forse ti fa andare sulla strada giusta, però.

    /// <summary>
    /// Sets the write-only dependency property.
    /// </summary>
    public string MyWriteOnlyDependencyProperty
    {
        set { SetValue(MyWriteOnlyDependencyPropertyProperty, value); }
    }

    private string _theRealSetValue;

    private bool _ignorePropertyChange;

    /// <summary>
    /// Identifies the MyWriteOnlyDependencyProperty dependency property.
    /// </summary>
    public static readonly DependencyProperty MyWriteOnlyDependencyPropertyProperty =
        DependencyProperty.Register(
            "MyWriteOnlyDependencyProperty",
            typeof(string),
            typeof(TemplatedControl1),
            new PropertyMetadata(null, OnMyWriteOnlyDependencyPropertyPropertyChanged));

    /// <summary>
    /// MyWriteOnlyDependencyPropertyProperty property changed handler.
    /// </summary>
    /// <param name="d">TemplatedControl1 that changed its MyWriteOnlyDependencyProperty.</param>
    /// <param name="e">Event arguments.</param>
    private static void OnMyWriteOnlyDependencyPropertyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        TemplatedControl1 source = d as TemplatedControl1;
        if (source._ignorePropertyChange)
        {
            source._ignorePropertyChange = false;
            return;
        }
        string value = e.NewValue as string;

        source._theRealSetValue = value;

        // Revert, since this should never be accessible through a read
        source._ignorePropertyChange = true;
        source.SetValue(e.Property, e.OldValue);
    }

Sembra che è possibile utilizzare il CoerceValueCallback associato alla proprietà tramite il FrameworkPropertyMetadata applicata nella definizione proprietà di dipendenza. Basta installare un callback che prende il secondo argomento, il nuovo valore, lo passa all'oggetto tramite il proprio meccanismo di sola scrittura, quindi restituisce null (o per i tipi di valore, default(T)).

E 'vero che "NET ricorda il valore originale prima di coercizione", ma non verrà propagato tramite data-binding. Le chiamate a GetValue restituirà il valore di coercizione, che non ci siano perdite nulla.

Sto usando questo per implementare unidirezionali setter di convenienza per il valore della mia proprietà primaria, che è una sequenza di byte. Un utente può legare una stringa, ad esempio, per impostare la proprietà primaria alle byte codificati (ASCII o UTF-8, a seconda quale proprietà è impostata). Ma non tutte le sequenze di byte sono validi UTF-8, quindi non è possibile invertire la conversione e la lettura di una stringa indietro attraverso la proprietà convenienza.

public string AsciiData
{
    set { BinaryArray = Encoding.ASCII.GetBytes(value); }
}

public static readonly DependencyProperty AsciiDataProperty =
    DependencyProperty.Register("AsciiData",
        typeof(string),
        typeof(HexView),
        new FrameworkPropertyMetadata(null, CoerceAsciiData));

private static object CoerceAsciiData(DependencyObject target, object value)
{
    (target as HexView).AsciiData = value as string;
    return null;
}

Il gestore di coercizione può essere rimosso tramite la sostituzione dei metadati, quindi questo non è fornire sicurezza , ma impedirà agli sviluppatori di creare accidentalmente accoppiamento in modi sbagliati.

Sono confuso sul motivo per cui non si può semplicemente avere il 'get' tornare nulla di utile?

Ma Inoltre, forse semplicemente non implementa l' 'OnMyWriteOnlyDependencyPropertyPropertyChanged', nell'esempio di Jeff.

Nessun vero motivo per avere l'evento, se nessuno può leggere, giusto?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top