Pergunta

Eu preciso saber qual é o procedimento para fazer uma dependência da propriedade somente para gravação. Eu posso ver que a classe DependencyProperty não tem um método especial "Register" para propriedades somente gravação, mas não tenho idéia se o método RegisterAttached pode aplicar-se o que estou tentando fazer.

Esta propriedade precisa ser uma dependência da propriedade, em vez de uma propriedade CLR simples. Internamente, minha classe requer um PropertyChangedCallback nesta propriedade, a fim de permanecer estável.

Eu sei que a dependência-propriedades somente gravação pode ser criado, pois afirma-se claramente em:
Pro C # 2008 eo .NET 3.5 Platform , página 1061 .
No entanto, este é o único lugar onde eu posso até achar "propriedade de dependência" e "escrever apenas" na mesma página. E este autor, aparentemente, não acho que era necessário para realmente mostrar ao leitor o procedimento para outra coisa senão uma leitura-escrita dependência-propriedade básica. Claro, este livro pode ser uma carga de BS - mas este livro analisa bastante normal, então eu acho que é uma aposta bastante segura de que o autor está correta. Presumo que a falta de informação na internet decorre do fato de que ninguém geralmente precisa fazer uma propriedade como esta.

Eu sei que parece muito questionável querer fazer o seu próprio só de escrita dependência-propriedade. Eu lhe asseguro que faz sentido onde eu o quero. Minha classe tem uma propriedade cujo valor só é útil ao defini-lo objeto. Se outro objeto foram para solicitar o valor dessa propriedade mais tarde, não seria capaz de fazer qualquer sentido racional fora do valor sem conhecer o contexto original do setter.

Esta propriedade não se destina a ser utilizado para fins informativos. Deixando objetos fora tentar usar o valor da propriedade desta forma é problemático, perigosa e um risco de segurança. Então eu acredito que o melhor projeto é proibir operações de leitura sobre essa propriedade. Quem estiver usando minha classe vai achar que eles são forçados a usar a classe a forma como foi concebido, que vai funcionar muito melhor e mais limpa no final.

Foi útil?

Solução

Você não pode, este parece ser por design. Embora eu possa compreender a sua abordagem para o mencionado livro e estou em nenhuma maneira a questionar a sua qualidade, eu ainda presumir que isso seja algum tipo de copiar e colar ou problema semelhante. Aqui está o meu raciocínio:

WPF código de sistema de propriedade

projeto WPF sistema de propriedade

  • Mais importante, 'A atual implementação do WPF do seu processador XAML é inerentemente propriedade de dependência consciente. Os métodos WPF XAML sistema utiliza processadores propriedades para as propriedades de dependência de carga quando binário XAML e processamento de atributos que são as propriedades de dependência. Isso ignora efetivamente os invólucros de propriedade. ', consulte XAML Carregando e Dependência propriedades .
  • O mais importante, 'As propriedades de dependência geralmente deve ser considerado como propriedades públicas. A natureza dos impede que o Windows Presentation Foundation (WPF) sistema de propriedade a capacidade de fazer garantias de segurança sobre um valor de propriedade de dependência. ', consulte Dependência Segurança Patrimonial .

Especialmente os dois últimos pontos são delineando a restrição de design, que os valores de propriedade de dependência são sempre acessível através de GetValue () / SetValue () , não importa se os seus invólucros CLR são de acesso restrito ou disponíveis em tudo, com a única exceção sendo o especificamente responsável por Read-Only Dependency Properties .

Por conseguinte, como Jeffs resposta já implica, apenas removendo o getter por exemplo, não realmente impedir que alguém acessando a propriedade através de GetValue () , embora isso possa, pelo menos, 'reduzir o namespace imediatamente exposta de uma classe personalizada' . A utilidade de qualquer solução alternativa semântica de fazer o propevalor rty um pouco menos visível / acessível e o valor recuperado inerentemente inútil para clientes como sugerido por Jeff depende do seu cenário em particular, é claro.

Outras dicas

Interessante, este é definitivamente um cenário raro, eu estaria interessado em ouvir mais no que ele permite.

Você consideraria a idéia de fornecer um valor inválido (como null) para leituras através da ligação ou GetValue, enquanto que apenas não ter um getter CLR?

Utilize uma DependencyProperty privada para armazenar o valor "real" você se preocupa, ou apenas uma variável de membro particular.

Na propriedade mudou de retorno de chamada, sempre reverter o valor de volta para o valor original, enquanto armazenar afastado o novo valor que foi definido.

Passo a maior parte do meu tempo fazendo o desenvolvimento de controle Silverlight agora, para esta propriedade funciona em WPF e Silverlight da terra, e não usa coercian ou diversão qualquer coisa assim. Talvez você fica indo no caminho certo, no entanto.

    /// <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);
    }

Parece que você pode usar o CoerceValueCallback associada com a propriedade através da FrameworkPropertyMetadata aplicada na definição de propriedade de dependência. Basta instalar um callback que leva o segundo argumento, o novo valor, passa para o objeto através do seu próprio mecanismo só de escrita, em seguida, retorna null (ou para tipos de valor, default(T)).

É verdade que ".NET lembra o valor original antes da coerção", mas não vai ser propagada através de ligação de dados. Chamadas para GetValue irá retornar o valor coagido, que não faz nada vazamento.

Eu estou usando isso para implementar setters conveniência de sentido único para o valor da minha propriedade primária, que é uma seqüência de bytes. Um utilizador pode ligar-se uma cadeia de caracteres, por exemplo, para definir a propriedade principal para os bytes codificados ASCII (ou UTF-8, dependendo do que é propriedade conjunto). Mas nem todas as seqüências de bytes são válidos UTF-8, por isso não é possível reverter a conversão e ler um back corda através do estabelecimento de conveniência.

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;
}

O manipulador de coerção podem ser removidos através de substituição de metadados, de modo que este não está fornecendo segurança , mas vai impedir que os desenvolvedores acidentalmente criando acoplamento de maneiras erradas.

Estou confuso sobre o porquê você não pode simplesmente ter o 'ficar' nada de retorno útil?

Mas, além disso, talvez você simplesmente não implementar o 'OnMyWriteOnlyDependencyPropertyPropertyChanged', no exemplo de Jeff.

Não há razão real para ter o evento, se ninguém pode lê-lo, certo?

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top