Nathan Anderson
Nathan Anderson

Reputation: 19

Address problems with bitmap thumbnails

Wandering If I can get help, the combobox lists hdds, when clicked I would like the listbox to list bitmap image thumbnails from that corrosponding hdd (each selected HDD is converted to a string which I hope to use as the address to get the thumbnails, I originally had help to get this to work with just full images but because thats slow I'm experimenting with thumbnails, so far I get no errors but nothing shows in the listbox and Im sure I have binded

    public MainWindow()
    {
        InitializeComponent();
        DataContext = this;
    }

    private void Window_Loaded(object sender, RoutedEventArgs e) //Window Loaded Event
    {
        ///Load Avaliable Drives Into ComboBox
        string[] drives = Environment.GetLogicalDrives(); //Drive Letters, Into A String Array

        foreach (string drive in drives)
        {
            HDDSelectionBox.Items.Add(drive); //Adds Each Drive Letter As A Combox Box Item
        }


        string root = (HDDSelectionBox.SelectedItem.ToString()); //Contains Directory Path For Images
        string[] supportedExtensions = new[] { ".bmp", ".jpeg", ".jpg", ".png", ".tiff" };
        var files = System.IO.Directory.EnumerateFiles(root, "*.*").Where(s => supportedExtensions.Contains(System.IO.Path.GetExtension(s).ToLower()));

        List<Photos> images = new List<Photos>();
        if (HDDSelectionBox.SelectedItem != null) //If a item has been selected
        {
        foreach (var file in files)
            {
                Photos id = new Photos()
                {
                    Path = file,
                    FileName = System.IO.Path.GetFileName(file),
                    Extension = System.IO.Path.GetExtension(file)
                };

                BitmapImage img = new BitmapImage();
                img.BeginInit();
                img.CacheOption = BitmapCacheOption.OnLoad;
                img.UriSource = new Uri(file, UriKind.Absolute);
                img.EndInit();
                id.Width = img.PixelWidth;
                id.Height = img.PixelHeight;

                // I couldn't find file size in BitmapImage
                FileInfo fi = new FileInfo(file);
                id.Size = fi.Length;
                images.Add(id);
            }

            ImageListBox.ItemsSource = images;
        }
    }

}


public class Photos
{
    /// <summary>
    /// A name for the image, not the file name.
    /// </summary>
    public string Name { get; set; }

    /// <summary>
    /// A description for the image.
    /// </summary>
    public string Description { get; set; }

    /// <summary>
    /// Full path such as c:\path\to\image.png
    /// </summary>
    public string Path { get; set; }

    /// <summary>
    /// The image file name such as image.png
    /// </summary>
    public string FileName { get; set; }

    /// <summary>
    /// The file name extension: bmp, gif, jpg, png, tiff, etc...
    /// </summary>
    public string Extension { get; set; }

    /// <summary>
    /// The image height
    /// </summary>
    public int Height { get; set; }

    /// <summary>
    /// The image width.
    /// </summary>
    public int Width { get; set; }

    /// <summary>
    /// The file size of the image.
    /// </summary>
    public long Size { get; set; }

}

}

Upvotes: 0

Views: 111

Answers (1)

Mark Feldman
Mark Feldman

Reputation: 16119

First create a base model that you can use to do property notifications (the XAML controls need this in order to respond to changes:

public abstract class ObservableObject : INotifyPropertyChanged
{
    protected ObservableObject()
    {
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged<T>(Expression<Func<T>> propertyExpresion)
    {
        var property = (MemberExpression)propertyExpresion.Body;
        this.OnPropertyChanged(property.Member.Name);
    }

    protected void OnPropertyChanged(string propertyName)
    {
        if (this.PropertyChanged != null)
        {
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    protected void SetValue<T>(ref T refValue, T newValue, Expression<Func<T>> propertyExpresion)
    {
        if (!object.Equals(refValue, newValue))
        {
            refValue = newValue;
            this.OnPropertyChanged(propertyExpresion);
        }
    }

    protected void SetValue<T>(ref T refValue, T newValue, Action valueChanged)
    {
        if (!object.Equals(refValue, newValue))
        {
            refValue = newValue;
            valueChanged();
        }
    }

    protected void SetValue<T>(ref T refValue, string propertyName, T newValue)
    {
        if (!object.Equals(refValue, newValue))
        {
            refValue = newValue;
            this.OnPropertyChanged(propertyName);
        }
    }
}

Now create a model that enumerates your hard drive and images and creates thumbnails:

public class ImagesModel : ObservableObject
{
    private ObservableCollection<string> _HardDrives;
    public ObservableCollection<string> HardDrives
    {
        get {return this._HardDrives;}
        set {this._HardDrives = value; OnPropertyChanged(() => this.HardDrives);}
    }

    private string _CurrentDrive;
    public string CurrentDrive
    {
        get {return this._CurrentDrive;}
        set {
            this._CurrentDrive = value;
            OnPropertyChanged(() => this.CurrentDrive);

            // enumerate files in this drives
            string[] supportedExtensions = new[] { ".bmp", ".jpeg", ".jpg", ".png", ".tiff" };
            this.Images = new ObservableCollection<PhotoModel>(
                System.IO.Directory.EnumerateFiles(value, "*.*")
                .Where(s => supportedExtensions.Contains(System.IO.Path.GetExtension(s).ToLower()))
                .Select(filename => new PhotoModel(filename)));
        }
    }

    private ObservableCollection<PhotoModel> _Images;
    public ObservableCollection<PhotoModel> Images
    {
        get {return this._Images;}
        set {this._Images = value; OnPropertyChanged(() => this.Images);}
    }

    private PhotoModel _CurrentImage;
    public PhotoModel CurrentImage
    {
        get {return this._CurrentImage;}
        set {this._CurrentImage = value; OnPropertyChanged(() => this.CurrentImage);}
    }

    public ImagesModel()
    {
        this.HardDrives = new ObservableCollection<string>(Environment.GetLogicalDrives());
    }
}

public class PhotoModel : ObservableObject
{
    private string _FileName;
    public string FileName
    {
        get {return this._FileName;}
        private set { this._FileName = value; OnPropertyChanged(() => this.FileName);}
    }

    private ImageSource _Image;
    public ImageSource Image {
        get {return this._Image;}
        private set {this._Image = value;OnPropertyChanged(() => this.Image);}
    }

    public PhotoModel(string filename)
    {
        this.FileName = filename;
        BitmapImage img = new BitmapImage();
        img.BeginInit();
        img.CacheOption = BitmapCacheOption.OnLoad;
        img.UriSource = new Uri(filename, UriKind.Absolute);
        img.DecodePixelWidth = 64;  // or whatever
        img.EndInit();
        this.Image = img;
    }
}

Obviously you'll need to create an instance of this class and assign it to your windows's DataContext:

public MainWindow()
    {
        InitializeComponent();
        this.DataContext = new ImagesModel();
    }

Finally add your ComboBox and ListBox to the window, set up your bindings and override the ListBox item template to display the images:

<Grid>
    <ComboBox ItemsSource="{Binding HardDrives}" SelectedValue="{Binding CurrentDrive}" HorizontalAlignment="Left" Margin="27,35,0,0" VerticalAlignment="Top" Width="120"/>
    <ListBox ItemsSource="{Binding Images}" SelectedValue="{Binding CurrentImage}" HorizontalAlignment="Left" Height="212" Margin="27,87,0,0" VerticalAlignment="Top" Width="188">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <Image Width="64" Height="64" Source="{Binding Image}" />
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

</Grid>

Upvotes: 1

Related Questions