Pergunta

Estou tentando vincular uma lista de objetos personalizados a uma imagem WPF como esta:

<Image>
    <Image.Source>
        <BitmapImage UriSource="{Binding Path=ImagePath}" />
    </Image.Source>
</Image>

Mas não funciona.Este é o erro que estou recebendo:

"A propriedade 'UriSource' ou a propriedade 'StreamSource' deve ser definida."

o que estou perdendo?

Foi útil?

Solução

O WPF possui conversores integrados para determinados tipos.Se você vincular as imagens Source propriedade para um string ou Uri valor, nos bastidores o WPF usará um Conversor de fonte de imagem para converter o valor em um ImageSource.

Então

<Image Source="{Binding ImageSource}"/>

funcionaria se a propriedade ImageSource fosse uma representação de string de um URI válido para uma imagem.

É claro que você pode criar seu próprio conversor de Binding:

public class ImageConverter : IValueConverter
{
    public object Convert(
        object value, Type targetType, object parameter, CultureInfo culture)
    {
        return new BitmapImage(new Uri(value.ToString()));
    }

    public object ConvertBack(
        object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}

e use assim:

<Image Source="{Binding ImageSource, Converter={StaticResource ImageConverter}}"/>

Outras dicas

Este artigo de Atul Gupta tem um código de exemplo que cobre vários cenários:

  1. Vinculação regular de imagem de recurso à propriedade Source em XAML
  2. Vinculando imagem de recurso, mas por trás do código
  3. Vinculando imagem de recurso no code-behind usando Application.GetResourceStream
  4. Carregando imagem do caminho do arquivo via fluxo de memória (o mesmo se aplica ao carregar dados de imagem de blog do banco de dados)
  5. Carregando imagem do caminho do arquivo, mas usando ligação a um caminho de arquivo Propriedade
  6. Vinculando dados de imagem a um controle de usuário que possui controle de imagem internamente por meio de propriedade de dependência
  7. Igual ao ponto 5, mas também garantindo que o arquivo não fique bloqueado no disco rígido

Você também pode simplesmente definir o atributo Source em vez de usar os elementos filhos.Para fazer isso, sua classe precisa retornar a imagem como uma imagem bitmap.Aqui está um exemplo de uma maneira que eu fiz

<Image Width="90" Height="90" 
       Source="{Binding Path=ImageSource}"
       Margin="0,0,0,5" />

E a propriedade da classe é simplesmente esta

public object ImageSource {
    get {
        BitmapImage image = new BitmapImage();

        try {
            image.BeginInit();
            image.CacheOption = BitmapCacheOption.OnLoad;
            image.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
            image.UriSource = new Uri( FullPath, UriKind.Absolute );
            image.EndInit();
        }
        catch{
            return DependencyProperty.UnsetValue;
        }

        return image;
    }
}

Suponho que possa dar um pouco mais de trabalho do que o conversor de valor, mas é outra opção.

Você precisa ter uma implementação de Conversor de valor interface que converte o uri em uma imagem.Sua implementação do Convert do IValueConverter será mais ou menos assim:

BitmapImage image = new BitmapImage();
image.BeginInit();
image.UriSource = new Uri(value as string);
image.EndInit();

return image;

Então você precisará usar o conversor na sua ligação:

<Image>
    <Image.Source>
        <BitmapImage UriSource="{Binding Path=ImagePath, Converter=...}" />
    </Image.Source>
</Image>

O problema da resposta escolhida aqui é que ao navegar para frente e para trás, o conversor será acionado toda vez que a página for mostrada.

Isso faz com que novos identificadores de arquivo sejam criados continuamente e bloqueará qualquer tentativa de exclusão do arquivo porque ele ainda está em uso.Isso pode ser verificado usando o Process Explorer.

Se o arquivo de imagem puder ser excluído em algum momento, um conversor como este poderá ser usado:usando XAML para vincular a um System.Drawing.Image em um controle System.Windows.Image

A desvantagem desse método de fluxo de memória é que as imagens são sempre carregadas e decodificadas e nenhum armazenamento em cache pode ocorrer:"Para impedir que as imagens sejam decodificadas mais de uma vez, atribua a propriedade Image.Source de um URI em vez de usar fluxos de memória" Fonte:"Dicas de desempenho para aplicativos da Windows Store usando XAML"

Para resolver o problema de desempenho, o padrão de repositório pode ser usado para fornecer uma camada de cache.O cache pode ocorrer na memória, o que pode causar problemas de memória, ou como arquivos em miniatura que residem em uma pasta temporária que pode ser limpa quando o aplicativo é encerrado.

você pode usar

Classe ImageSourceConverter

para conseguir o que você quer

    img1.Source = (ImageSource)new ImageSourceConverter().ConvertFromString("/Assets/check.png");
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top