UriSource de imagem e vinculação de dados
-
09-06-2019 - |
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?
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:
- Vinculação regular de imagem de recurso à propriedade Source em XAML
- Vinculando imagem de recurso, mas por trás do código
- Vinculando imagem de recurso no code-behind usando Application.GetResourceStream
- 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)
- Carregando imagem do caminho do arquivo, mas usando ligação a um caminho de arquivo Propriedade
- Vinculando dados de imagem a um controle de usuário que possui controle de imagem internamente por meio de propriedade de dependência
- 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");