c# - 如何在 Wpf 中下载内容和更新 UI?

标签 c# wpf

我在使用 ui 更新从服务器下载多个图像时遇到问题。问题是我在服务器上有壁纸文件夹并且我想下载图像,我运行后台工作程序来下载图像并更新我的 UI,一旦我的所有图像都下载完成(BackgroundWorker_Completed),我的 UI 更新就会完成。但是我希望每次下载一个图像文件夹时更新我的​​ UI,如下图所示。

enter image description here

在上面给出的示例中,每个文件夹都包含多个图像,例如电影、游戏、印度等,并且它们具有所属类别的图像,例如在电影中,它们是文件夹,比如 Man Of Steel、Priest 等。现在,当我下载我的图像时,它们应该在 UI 上可见,每次它们最终都不会一次下载。下载壁纸的代码如下:


下载图片的后台工作代码

  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
                {

                }

            }

后台 worker 已完成在 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)
            {

            }
        }

后台调用的图片下载代码

    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);
                        }
                    }
                }
            }
        }

最佳答案

要了解如何异步下载大量图像同时在 ListBox 中显示它们,请查看以下简化的 View 模型,它为所有下载的图像声明一个集合属性和一个 async 执行下载的方法。

下载是异步的,因为该方法调用(并等待)异步 HttpClient.GetByteArrayAsync() 方法。

为了演示,它从 openstreetmap.org 下载 256 张( map 图 block )图像。

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));
                }
            }
        }
    }
}

您可以设置 MainWindow 的 DataContext 并在 Loaded 事件处理程序中开始下载,如下所示:

public MainWindow()
{
    InitializeComponent();

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

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

最后,ListBox 的 XAML 可能如下所示:

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

关于c# - 如何在 Wpf 中下载内容和更新 UI?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37877316/

相关文章:

c# - 如何将一个物体的局部轴旋转到另一个物体?

c# - 在后台工作线程中使用 C# 全局变量是否安全

C# 将混合 JSON 转换为对象

c# - 如何创建带有倾斜边框的文本框和标签?

c# - 包含列表的对象的 ObservableCollection

c# - 401 运行执行 HttpWebRequest 的 C# 应用程序时出现身份验证错误

c# - 使用未包装的集合反序列化 XML 时遇到问题

c# - 如何在 "Visibility"类别而不是 "Other"下声明 DependencyProperty ?

wpf - 如何单击文本框(或标签)来切换复选框

c# - 替换: One Property in ViewModel for each TextBox with B: One property returning a (observable) collection