Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
118 views
in Technique[技术] by (71.8m points)

c# - How to download content and update UI in Wpf?

I am having an issue in downloading multiple image from server with ui updation. Problem is this that I have folders of wallpaper on server and I want to download images, I run a background worker to download images and to update my UI and my UI updation will be done once my all images gets downloaded(BackgroundWorker_Completed). But I want my UI to be updated every time when one folder of images gets downloaded as shown in below given image.

enter image description here

In above given example every folder contains multiple images such as Movies, Games, India etc and they have images of their belonging category e.g. in movies their are folders say Man Of Steel, Priest etc. Now when I am downloading my images they should be visible on UI every they gets downloads not in once at last. Code for downloading wallpaper given below:


Background Worker Code For Downloading Images

  void worker_DoWork(object sender, DoWorkEventArgs e)
            {
                try
                {
                    DataSet dsFile = Global.ReadConfig;

                    XDocument xDoc = XDocument.Load(dsFile.Tables[0].Rows[0][8].ToString());
                    string s = xDoc.Root.Name.ToString();
                    var countNode = xDoc.Root.Elements().Count();
                    for (int i = 0; i < countNode; i++)
                    {
                        XNode childNode = xDoc.Root.Nodes().ElementAt(i);
                        XElement ele = (XElement)childNode;
                        string path = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + "\Wallpaper" + ele.Name;

                        var movieList = from a in xDoc.Root.Descendants(ele.Name).Elements()
                                        select a;
                        foreach (var a in movieList)
                        {
                            string newpath = path + "" + a.Value;
                            DirectoryInfo di = new DirectoryInfo(newpath);
                            if (!di.Exists)
                            {
                                DirectoryInfo dinew = Directory.CreateDirectory(newpath);
                                filedownload(dsFile.Tables[0].Rows[0][1].ToString() + "/Wallpaper/" + ele.Name + "/" + dinew.Name + "/", newpath + "");   
                            }
                        }
                        //new DesktopThemes.App_Page.MainWindow().getWallLink(ele.Name.LocalName);
                    }
                }
                catch
                {

                }

            }

Background Worker Completed to display image on UI

void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            string N = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + @"Wallpaper" ;

            Random random = new Random();

            List<String> backimage = new List<String>();

            DirectoryInfo diback = new DirectoryInfo(N);
            // diback.GetFiles();

            Directory.GetFiles(N, "*.*", SearchOption.AllDirectories);

            foreach (var imagename in diback.GetFiles("*.jpg", SearchOption.AllDirectories))
            {
                backimage.Add(imagename.Directory + "" + imagename.Name);
            }
            try
            {
                Image image = new Image();
                Uri add = new Uri(backimage[random.Next(0, backimage.Count - 1)]);
                image.Source = new BitmapImage(add);

                pnlBackground.Source = image.Source;
                this.Photos.Path = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + @"Wallpaper";
            }
            catch (Exception ex)
            {

            }
        }

Code For downloading images Which is being called from background worker

    public static void filedownload(String url, string downloadlocation)
        {
            FtpWebRequest ftpRequest = (FtpWebRequest)WebRequest.Create(url);
            ftpRequest.Credentials = new NetworkCredential(@username, @password);
            ftpRequest.Method = WebRequestMethods.Ftp.ListDirectory;
            FtpWebResponse response = (FtpWebResponse)ftpRequest.GetResponse();

            StreamReader streamReader = new StreamReader(response.GetResponseStream());
            List<string> directories = new List<string>();
            string line = streamReader.ReadLine();
            while (!string.IsNullOrEmpty(line))
            {
                directories.Add(line);
                line = streamReader.ReadLine();
            }
            streamReader.Close();
            using (WebClient ftpClient = new WebClient())
            {
                ftpClient.Credentials = new System.Net.NetworkCredential(@username, @password);
                for (int i = 0; i <= directories.Count - 1; i++)
                {
                    if (directories[i].Contains("."))
                    {
                        string path = url + directories[i].ToString();
                        string trnsfrpth = downloadlocation + directories[i].ToString();                            if (!new System.IO.FileInfo(trnsfrpth).Exists)
                        {
                            ftpClient.DownloadFile(path, trnsfrpth);
                        }
                    }
                }
            }
        }
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

To get an idea of how one could asynchronously download a large number of images while simultaneously showing them in a ListBox, take a look at the following simplified view model, which declares a collection property for all downloaded images and an async method that performs the download.

The download is asynchronous because the method calls (and awaits) the async HttpClient.GetByteArrayAsync() method.

For demonstration, it downloads 256 (map tile) images from openstreetmap.org.

public class ViewModel
{
    public ObservableCollection<ImageSource> Images { get; private set; }
        = new ObservableCollection<ImageSource>();

    public async Task DownloadImages()
    {
        var httpClient = new HttpClient();

        for (int y = 0; y < 16; y++)
        {
            for (int x = 0; x < 16; x++)
            {
                var url = string.Format(
                    "http://tile.openstreetmap.org/4/{0}/{1}.png", x, y);

                // the await here makes the download asynchronous
                var buffer = await httpClient.GetByteArrayAsync(url);

                using (var stream = new MemoryStream(buffer))
                {
                    Images.Add(BitmapFrame.Create(
                        stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad));
                }
            }
        }
    }
}

You may set up your MainWindow's DataContext and start the download in a Loaded event handler like this:

public MainWindow()
{
    InitializeComponent();

    var viewModel = new ViewModel();
    DataContext = viewModel;

    Loaded += async (s, e) => await viewModel.DownloadImages();
}

Finally, the ListBox's XAML might look like this:

<ListBox ItemsSource="{Binding Images}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <Image Source="{Binding}" />
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...