niedziela, 7 listopada 2010

Przeglądanie zdjęć na dysku

Czas żeby wykorzystać napisaną w ostatnim poście kontrolkę do wyświetlania obrazków przedstawioną w poprzednim poście. Na razie wykorzystywana będzie jedynie podczas przeglądania struktury dysku. Sprzężenie między aktualnym katalogiem a zdjęciami również będzie tymczasowe.

Aby w prosty sposób móc przekazać listę zdjęć do kontrolki ImageListView wystawiona na zewnątrz niej zostanie jedna DependencyProperty typu ObservableCollecion<Photo>. Dzięki temu bindowanie może być zrobione z poziomu XAML'a. 
public ObservableCollection<Photo> Photos
{
 get
 {
  return (ObservableCollection<Photo>)GetValue(PhotosProperty);
 }
 set
 {
  SetValue(PhotosProperty, value);
 }
}

public static readonly DependencyProperty PhotosProperty = DependencyProperty.Register(
 PhotosPropertyName,
 typeof(ObservableCollection<Photo>),
 typeof(ImageListView),
 new PropertyMetadata(new ObservableCollection<Photo>(), new PropertyChangedCallback(OnPhotosListChanged)));
Przy każdej zmianie zawartości listy zdjęć zostanie wywołana funkcja OnPhotosListChanged. Jej jedynym zadaniem będzie wysłanie komunikatu poprzez niedawno stworzoną statyczną klasę AppMessages.
private static void OnPhotosListChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
 AppMessages.PhotoSourceChangedMessage.Send(e.NewValue as ObservableCollection<Photo>);
}
Wiadomość ta jest odbierana w konstruktorze kontrolki i po prostu przypisuje nowo otrzymaną listę to właściwości użytej do przechowywania listy:
AppMessages.PhotoSourceChangedMessage.Register(this,
 p => Photos = p);

Do przeglądania zdjęć na dysku potrzebne jest jedynie, aby lista zdjęć była odświeżona za każdym razem, gdy zmieni się zaznaczony folder. Można to osiągnąć przez zbindowanie aktualnie wybranego katalogu z kontrolki DirectoryTreeView do właściwości Photos kontrolki ImageListView. 
<my:ImageListView Photos="{Binding CurrentDirectory, Converter={StaticResource DirectoryToPhotosConverter}, ElementName=directoryTreeView}"/>
Oczywiście nie zrzucamy na kontrolkę wyświetlającą odpowiedzialności z pobranie listy zdjęć z dysku. Dlatego też użyty jest konwerter zamieniający ścieżkę do katalogu na listę obiektów Photo, wskazujących na zdjęcia z tego katalogu. 
[ValueConversion(typeof(string), typeof(ObservableCollection<Photo>))]
public class DirectoryToPhotosConverter : IValueConverter
{
 public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
 {
  string str = value as string;

  if (str != null)
  {
   IList<Photo> photos = ImageLoader.GetListOfPhotosFromPath(str);
   if (photos != null)
    return new ObservableCollection<Photo>(photos);
  }

  return new ObservableCollection<Photo>();
 }

 public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
 {
  throw new NotImplementedException();
 }
}
Konwerter ten wykorzystuje metodę GetListOfPhotosFromPath z klasy ImageLoader:
public class ImageLoader
{
 public static List<Photo> GetListOfPhotosFromPath(string path)
 {
  List<Photo> result = new List<Photo>();

  if (Directory.Exists(path))
  {
   result.AddRange(getPhotosByExt(path, "*.jpg"));
   result.AddRange(getPhotosByExt(path, "*.jpeg"));
   result.AddRange(getPhotosByExt(path, "*.png"));
   result.AddRange(getPhotosByExt(path, "*.gif"));
  }

  return result;
 }

 private static List<Photo> getPhotosByExt(string path, string ext)
 {
  List<Photo> result = new List<Photo>();

  string[] files = Directory.GetFiles(path, ext);
  foreach (var f in files)
  {
   result.Add(new Photo
   {
    Path = f,
    Description = Path.GetFileName(f)
   });
  }
  return result;
 }
}
Jest to trochę naiwna implementacja zakładająca, że istnieją tylko cztery rodzaje plików graficznych, ale to sprawdzenia poprawności działania w zupełności wystarcza.

Po połączeniu tych elementów można już przeglądać katalogi w poszukiwaniu zdjęć :P

Brak komentarzy:

Prześlij komentarz