Show progress of loading an image from file

786 views Asked by At

i'm writing a .NET 4.0 WPF application and i need to load a large image (300 MB) from my hard disk. Loading the image takes a few seconds and i want to show the progress of it by using a progress-bar. I use an image with a BitmapImage as its source. The BitmapImage class provides the DownloadProgress event which is working fine if i load the image from the web. But it does not work if i load the image from my hdd.

Here is the MCVE: The xaml file:

<Window x:Class="progressbar.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:progressbar"
        Title="MainWindow" Height="Auto" Width="Auto">
    <Window.DataContext>
        <local:MainVM />
    </Window.DataContext>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="100"/>
            <ColumnDefinition Width="100"/>
            <ColumnDefinition Width="100"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="250"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Image Source="{Binding BitmapImg}" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3"/>
        <TextBox Text="{Binding Url, Mode=TwoWay}" Grid.Column="0" Grid.ColumnSpan="3" Grid.Row="1"/>
        <Button Content="Load local image file" Grid.Column="0" Grid.Row="2" Click="Button_Click"/>
        <Button Content="Load from url" Grid.Column="1" Grid.Row="2" Click="Button_Click_1"/>
        <ProgressBar Value="{Binding Progress}" Grid.Column="2" Grid.Row="2"/>
    </Grid>
</Window>

The code-behind:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Win32;


namespace progressbar
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow() {
            InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e) {
            var dc = DataContext as MainVM;
            if (dc == null) return;

            OpenFileDialog dialog = new OpenFileDialog();
            var res = dialog.ShowDialog();
            if (res == true) {
                dc.Url = dialog.FileName;
                dc.loadImage();
            }
        }

        private void Button_Click_1(object sender, RoutedEventArgs e) {
            var dc = DataContext as MainVM;
            if (dc == null) return;
            dc.loadImage();
        }
    }
}

And the ViewModel:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Media.Imaging;
using System.Windows.Input;
using System.ComponentModel;

namespace progressbar
{
    public class MainVM : INotifyPropertyChanged
    {
        private BitmapImage bmi = null;
        private Int32 _progress = 0;
        private String _url = "";

        public event PropertyChangedEventHandler PropertyChanged;

        public Int32 Progress {
            get { return _progress; }
            set {
                _progress = value;
                NotifyPropertyChanged("Progress");
            }
        }

        public String Url {
            get { return _url; }
            set {
                _url = value;
                NotifyPropertyChanged("Url");
            }
        }

        public BitmapImage BitmapImg {
            get { return bmi; }
            set { bmi = value; }
        }

        public MainVM() { }

        private void NotifyPropertyChanged(string propertyName = "") {
            if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        public void loadImage() {
            bmi = new BitmapImage();
            bmi.BeginInit();
            bmi.UriSource = new Uri(_url);
            bmi.DownloadProgress += new EventHandler<DownloadProgressEventArgs>(bmi_DownloadProgress);
            bmi.EndInit();
            NotifyPropertyChanged("BitmapImg");
        }

        void bmi_DownloadProgress(object sender, DownloadProgressEventArgs e) {
            Progress = e.Progress;
        }
    }
}

If you try to load an image from your hdd the progress will not be shown. Is there a way to do this?

Thanks in advance

0

There are 0 answers