Pergunta

É possível usar conversores de valor sem precisar defini -los com antecedência como recursos?

Agora eu tenho

<Window.Resources>
    <local:TrivialFormatter x:Key="trivialFormatter" />
</Window.Resources>

e

<Button Width="{Binding Width, 
               ElementName=textBox1, 
               UpdateSourceTrigger=PropertyChanged, 
               Converter={StaticResource trivialFormatter}}">

Não seria possível que, em vez de ter que declarar o recurso Trivialformatter na janela.Resources, eu pudesse encaminhá -lo diretamente da ligação da largura do botão? Algo como

Converter = {local:TrivialFormatter}

Obrigado

Foi útil?

Solução

No caso do tipo de singleton IValueConverters (por exemplo, eles não precisam de nenhum estado da instância de ligação atual) Eu uso conversores estáticos, ou seja::

Converter={x:Static SomeNamespace:SomeConverter.Instance}

Há também um ótimo post do Dr. WPF sobre o uso de uma extensão de marcação para torná -lo mais limpo aqui.

Outras dicas

Tecnicamente, acredito que você pode fazer isso, mas o XAML é tão horrível que faça com que a abordagem "muitos recursos triviais" pareça um refúgio de simplicidade e clareza em comparação:

<Button Height="50">
  <Button.Width>
    <Binding Path="Width" ElementName="textBox1" UpdateSourceTrigger="PropertyChanged">
      <Binding.Converter>
        <local:TrivialFormatter />
      </Binding.Converter>
    </Binding>
  </Button.Width>
</Button>

Eu não testei isso porque nem mesmo leitura Isso faz meus olhos lacrimejarem ...

Eu definitivamente examinaria a sugestão de Micah, que envolve o uso de uma instância estática de singleton do seu conversor. Mas outra coisa a considerar é que, se você estiver usando um padrão de apresentação separado, como o MVVM, muitas vezes pode evitar o requisito de um conversor de valor implementando a conversão no ViewModel.

Há muitas razões pelas quais você pode querer fazer isso.

Por um lado, é muito mais testável. Seus testes de unidade podem ter certeza de que tudo o que está saindo do ViewModel é o que será exibido pela interface do usuário. Você pode imaginar testar um requisito de que os valores do dólar devem seguir o formato da moeda da cultura atual, dois decimais devem ser usados, etc.

Outra boa razão é que exceções nos conversores de valor irão não Seja tratado como erros de validação, o que pode ser uma enorme dor na bunda no Silverlight. Mesmo se você definir o ValidateSonexceptions como TRUE na ligação, se o seu conversor de valor lançar uma exceção, o Silverlight apenas permitirá que ele se propus. Se, no entanto, você usar o ViewModel para fazer a conversão, uma exceção será tratada como um erro de validação.

A desvantagem é que você perde parte da "reutilização" de um conversor de valor de propósito geral.

Não conheço uma maneira de fazer isso da maneira que você está afirmando, mas eu apenas tentei isso como uma amostra e funcionou. No seu arquivo app.xaml.cs, você pode criar um método que use a reflexão para carregar os conversores.

private void Application_Startup(object sender, StartupEventArgs e)
{
    LoadConverters();
}

private void LoadConverters()
{
    foreach(var t in Assembly.GetExecutingAssembly().GetTypes())
    {
        if (t.GetInterfaces().Any(i => i.Name == "IValueConverter"))
        {
            Resources.Add(t.Name, Activator.CreateInstance(t));
        }
    }
}

Então você pode usar o conversor como este, na metade do caminho, eu acho.

<Button Width="{Binding Width, Converter={StaticResource TrivialFormatter}}" />

O problema com a abordagem que você está propondo é que o analisador XAML não sabe quando e quantas instâncias do seu conversor para criar. Criando -o como um recurso garante apenas uma instância.

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