2013-03-24 10 views
7

Sto tentando di visualizzare alcune immagini in un controllo ListView e non ho avuto esito positivo. Sto usando WVF MVVM e ListView è un holdover dalla semplice visualizzazione di semi e dati di classifica. (Vedi il mio post precedente: MVVM in WPF - How to alert ViewModel of changes in Model... or should I? se sei interessato!) Cioè, potrei usare qualcosa di diverso da ListView (se questo è il consiglio), ma mi piacerebbe comunque sapere come farlo con ListView, assumendo che sia fattibile. La mia proprietà mi legame nel ViewModel è:Visualizzazione di immagini in ListView (o qualcosa di meglio!) In MVVM WPF mediante associazione dati

public ObservableCollection<Image> PlayerCardImages{ 
    get{ 
     ObservableCollection<Image> results = new ObservableCollection<Image>(); 
     foreach (CardModel card in PlayerCards) 
     { 
      Image img = new Image(); 
      BitmapImage bi3 = new BitmapImage(); 
      bi3.BeginInit(); 
      // TODO: Pick card based on suit/rank. Just get 1 image working now 
      bi3.UriSource = new Uri("diamond-1.png", UriKind.Relative); 
      bi3.EndInit(); 
      img.Stretch = Stretch.Fill; 
      img.Source = bi3;    
      results.Add(img); 
     } 
     return results; 
    } 
} 

Nel mio codice XAML che sto usando:

<Window.Resources> 
<DataTemplate x:Key="ImageCell"> 
     <StackPanel Orientation="Horizontal"> 
      <Image Source="{Binding PlayerCardImages}" Width="200" Height="200" Stretch="Fill" ToolTip="Add tooltip"/> 
     </StackPanel> 
    </DataTemplate> 
</Window.Resources> 

<StackPanel Orientation="Vertical"> 
<Label Content="Player Cards"/> 
     <ListView Name="lvwTitles" ItemsSource="{Binding}" 
IsSynchronizedWithCurrentItem="True" 
SelectionMode="Single" ItemTemplate="{StaticResource ImageCell}" Height="59"> 
     </ListView> 
    </StackPanel> 

Questa idea è stata spudoratamente rubato da: WPF - bind images horizontally to ListView Tuttavia, esso doesn' t sembra che il database sia evidenziato dal mio punto di interruzione in PlayerCardImages che non viene colpito.

Ho anche provato il seguente codice XAML con un po 'meglio di fortuna:

<StackPanel Orientation="Vertical"> 
     <Label Content="Player Cards"/> 
     <ListView 

     AlternationCount="2" 
     DataContext="{StaticResource PlayerCardsGroups }" 
     ItemsSource="{Binding}" 
     > 
      <ListView.GroupStyle> 
       <StaticResourceExtension 
       ResourceKey="CardGroupStyle" 
       /> 
      </ListView.GroupStyle> 
      <ListView.View> 
       <GridView> 
        <GridViewColumn> 
       <Image Height="50" Width="40"></Image> 
        </GridViewColumn> 
       </GridView>     
      </ListView.View> 
     </ListView> 
    </StackPanel> 
    <Window.Resources> 
    <CollectionViewSource x:Key="PlayerCardsGroups" 
     Source="{Binding Path=PlayerCardImages}"> 
    </CollectionViewSource> 

    <GroupStyle x:Key="CardGroupStyle"> 
     <GroupStyle.HeaderTemplate> 
      <DataTemplate> 
       <TextBlock 
     x:Name="txt" 
     Background="{StaticResource Brush_HeaderBackground}" 
     FontWeight="Bold" 
     Foreground="White" 
     Margin="1" 
     Padding="4,2,0,2" 
     Text="Cards" 
     /> 
      </DataTemplate> 
     </GroupStyle.HeaderTemplate> 
    </GroupStyle> 

    <Style x:Key="CardItemStyle" TargetType="{x:Type ListViewItem}"> 
     <!-- 
    Stretch the content of each cell so that we can 
    right-align text in the Total Sales column. 
    --> 
     <Setter Property="HorizontalContentAlignment" Value="Stretch" /> 
     <!-- 
    Bind the IsSelected property of a ListViewItem to the 
    IsSelected property of a CustomerViewModel object. 
    --> 
     <Style.Triggers> 
      <MultiTrigger> 
       <MultiTrigger.Conditions> 
        <Condition Property="ItemsControl.AlternationIndex" Value="1" /> 
        <Condition Property="IsSelected" Value="False" /> 
        <Condition Property="IsMouseOver" Value="False" /> 
       </MultiTrigger.Conditions> 
       <Setter Property="Background" Value="#EEEEEEEE" /> 
      </MultiTrigger> 
     </Style.Triggers> 
    </Style> 

    </Window.Resources> 

questo codice va decisamente attraverso l'associazione dati - il mio punto di interruzione è colpito all'inizio del programma e ogni volta che gli elementi vengono aggiunti alla collezione. Ma nessuna immagine viene visualizzata. Piuttosto che torturarti con più XAML che non funziona, forse potrei chiedere a qualcuno di indicarmi alcuni codici/esempi/documenti che mostrano come associare un elenco di immagini a un ListView (o un altro controllo se ritieni davvero che ListView sia non appropriato). Si noti che la mia collezione è il materiale a cui mi sto impegnando. Ho notato che con molti esempi, sono vincolanti per una sottoproprietà. Cioè possono avere una collezione di album e per ogni album che associano alla sua immagine di proprietà (vedi: Showing items as images in a WPF ListView).

Qualsiasi idea o aiuto sarebbe molto apprezzata.

-Dave

Ulteriori informazioni.

sulla base dei suggerimenti di Clemens, ora ho questo codice per PlayerCardImages:

public ObservableCollection<ImageSource> PlayerCardImages 
    { 
     get 
     { 
      var results = new ObservableCollection<ImageSource>(); 

      //if (PlayerCards.Count == 0) 
      // return results; 
      //else 
      //{ 
      // results.Add(new BitmapImage(new Uri(@"Images\\" + "diamond-1.png", UriKind.Relative))); 
      //} 
      foreach (var card in PlayerCards) 
      { 
       results.Add(new BitmapImage(new Uri(@"Images\\" + GetCardFileName(card), UriKind.Relative))); 

      } 
      return results; 

     } 

ho usato il codice XAML esatto ha suggerito. Funziona quasi. Dico "quasi" perché ho notato uno strano comportamento per cui a volte 1 carta mostrava e qualche volta no (non ho mai avuto 2 carte). Tutte le carte ottenute da file e rilegature sembrano funzionare e ho rintracciato ciò che ritengo sia la chiave dell'ultimo bug rimanente (ed è BIZARRE). Se nel debugger, esamino i risultati e apro ulteriormente i risultati [0] nel debugger, visualizzo quella scheda! In realtà devo aprirlo [0] (vedi informazioni su altezza, larghezza, ecc.) Affinché funzioni. Inoltre se apro [1], visualizzo invece quella carta. Perché aprire le informazioni del debugger ha qualche effetto? Per quelli di voi che potrebbero chiedere, cosa succede se si aprono entrambe le carte nel debugger ... che non funziona. Ottengo un'eccezione scaduta dall'operazione. Dirò che forse i miei file di immagini sono grandi. Da 10 KB a 30 Kbyte. È questo il problema? Sto indovinando no, e che è un sottile problema con la lettura delle immagini o l'associazione. Cosa sta succedendo? Grazie, Dave

risposta

10

In primo luogo, non si deve utilizzare i controlli immagine nel tuo ViewModel. Hai già un controllo immagine nel DateTemplate della tua vista. Si desidera associare la proprietà Source di questo conntrol Immagine e la proprietà di origine di questa associazione non può essere un'altra immagine.

Invece il tuo ViewModel sarebbe o utilizzare ImageSource (o una classe derivata come BitmapImage) come tipo di immagine, in questo modo:

public ObservableCollection<ImageSource> PlayerCardImages 
{ 
    get 
    { 
     var results = new ObservableCollection<ImageSource>(); 
     foreach (var card in PlayerCards) 
     { 
      results.Add(new BitmapImage(new Uri(card.ImageUrl))); 
     } 
     return results; 
    } 
} 

O semplicemente gli URI di immagine o percorsi, in quanto v'è una conversione automatica da string a ImageSource costruito in WPF:

public ObservableCollection<string> PlayerCardImages 
{ 
    get 
    { 
     var results = new ObservableCollection<string>(); 
     foreach (var card in PlayerCards) 
     { 
      results.Add(card.ImageUrl); 
     } 
     return results; 
    } 
} 

si potrebbe ora associare proprietà del Listbox ItemsSource alla raccolta PlayerCardGames, e nel DataTemplate vi legano direttamente all'oggetto della collezione. Il DataContext di ListView deve essere impostato su un'istanza dell'oggetto che definisce la proprietà PlayerCardGames.

<ListView ItemsSource="{Binding PlayerCardGames}"> 
    <ListView.ItemTemplate> 
     <DataTemplate> 
      <StackPanel> 
       <Image Source="{Binding}" /> 
      </StackPanel> 
     </DataTemplate> 
    </ListView.ItemTemplate> 
</ListView> 

UPDATE: Come sembra che ci sia un problema con il caricamento dei file di immagine, si può provare il seguente metodo. Carica le immagini in modo sincrono e puoi eseguire il debugger.

public static ImageSource LoadImage(string fileName) 
{ 
    var image = new BitmapImage(); 

    using (var stream = new FileStream(fileName, FileMode.Open)) 
    { 
     image.BeginInit(); 
     image.CacheOption = BitmapCacheOption.OnLoad; 
     image.StreamSource = stream; 
     image.EndInit(); 
    } 

    return image; 
} 

È possibile utilizzare questo metodo nella PlayerCardGames proprietà getter in questo modo:

foreach (var card in PlayerCards) 
{ 
    results.Add(LoadImage(@"Images\\" + GetCardFileName(card))); 
} 
+0

Clemens, La ringrazio molto per la risposta. Ho implementato i tuoi suggerimenti e penso di essere molto vicino. Puoi dare un'occhiata alle mie modifiche nella parte inferiore del mio post originale? (Non c'era spazio nei commenti per inserire codice aggiuntivo). Grazie. Dave – Dave

+0

Difficile dire cosa sta andando male, ma puoi provare il metodo di caricamento che ho aggiunto alla mia risposta. – Clemens

+0

Clemens, grazie! Grazie! Grazie! Che funzioni. Per quello che vale, sembra che la linea su CacheOption sia la chiave. Ho commentato e le immagini non sono state visualizzate. Curiosamente, non sono riuscito a farli visualizzare usando il mio trucco di aprire i risultati nella finestra di controllo e di esaminare una carta. Saluti. – Dave

0

non ho davvero provare a riprodurre il problema, ma lo farò se questo non è risolverlo:

Nel suo primo blocco di XAML, penso che mescolato le associazioni. Questo sarebbe come me lo aspetto, ItemsSource alla ObservableCollection of Images, Image source to Image.

<Image Source="{Binding}" ... /> 
<ListView Name="lvwTitles" ItemsSource="{Binding PlayerCardImages}" ... /> 

Nel vostro secondo blocco, è omesso il Fonte di legame del tutto:

<Image Source="{Binding}" Height="50" Width="40" /> 
Problemi correlati