从另一个 class 访问 UI 控件

Access UI Control from another class

我想从另一个 class 更新我的进度视图,但不知道如何正确地做到这一点。

在我的 ViewController 中,我有一个启动任务的按钮,它从硬编码 link

下载文件
public void downloadTask()
        {
            NSUrl url = NSUrl.FromString("https://www.dropbox.com/s/5fsciuo0nprzvu6/TestDoc.docx?dl=0");

            var config = NSUrlSessionConfiguration.DefaultSessionConfiguration;
            NSUrlSession session = NSUrlSession.FromConfiguration(config, (new SimpleSessionDelegate() as INSUrlSessionDelegate), new NSOperationQueue());
            var downloadTask = session.CreateDownloadTask(NSUrlRequest.FromUrl(url));

            downloadTask.Resume();
        }

在我的 SimpleSessionDelegate class 中,我想在 DidWriteData 方法中更新我的进度视图。

public class SimpleSessionDelegate : NSUrlSessionDownloadDelegate
    {
        public override void DidFinishDownloading(NSUrlSession session, NSUrlSessionDownloadTask downloadTask, NSUrl location)
        {
            var documents = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
            var destinationPath = Path.Combine(documents, "Sample.docx");

            if (File.Exists(location.Path))
            {
                NSFileManager fileManager = NSFileManager.DefaultManager;
                NSError error;

                fileManager.Remove(destinationPath, out error);

                bool success = fileManager.Copy(location.Path, destinationPath, out error);

                if (!success)
                {
                    Console.WriteLine("Error during the copy: {0}", error.LocalizedDescription);
                }
            }
        }
        public override void DidWriteData(NSUrlSession session, NSUrlSessionDownloadTask downloadTask, long bytesWritten, long totalBytesWritten, long totalBytesExpectedToWrite)
        {
            new System.Threading.Thread(new System.Threading.ThreadStart(() =>
            {
                InvokeOnMainThread(() =>
                {
                    //how to access UI?
                });
            })).Start();
        }
    }

在您的 Page.xaml 中执行此操作:

<ContentPage .... >
    ...
    <ProgressBar Progress="{Binding ProgValue, Mode=TwoWay}" />
    ...
</ContentPage>

然后在 Page.xaml.cs 中执行此操作:

...
public partial class Page : ContentPage
{
    InitializeComponent();
    BindingContext = new PageViewModel();
}
...

现在您需要 PageViewModel class 在您的数据(模型)和您的视图之间创建一条路径:

using MvvmHelper;
using System;

namespace MyApp.ViewModels
{
    ...
    public class PageViewModel : BaseViewModel
    {
        ...
        public static int ProgValue { get; set; }
        ...
    }
}

现在,如果您从应用程序的每个位置更新 ProgValue 的值,它会自动更新进度条。

要使用 BaseViewModel,您需要安装
Mvvm Helper
或者在包管理器控制台类型:
Install-Package Refractored.MvvmHelpers

这种架构称为 MVVM(模型-视图-视图-模型)——正式名称为 MVC(模型-视图-控制器)

您可以尝试使用 Event 来更改 ViewController 的 UIProgressView 的进度。

首先在您的 ViewModel 中定义一个事件:

public delegate void DownloadProgressDelegate(float progress);
public event DownloadProgressDelegate DownloadEvent;

其次,将此事件传递给您的下载委托文件:

NSUrlSession session = NSUrlSession.FromConfiguration(config, (new SimpleSessionDelegate(DownloadEvent) as INSUrlSessionDelegate), new NSOperationQueue());
//Here is your SimpleSessionDelegate
event ViewModel.DownloadProgressDelegate DownloadEvent;
public SimpleSessionDelegate(ViewModel.DownloadProgressDelegate downloadEvent)
{
    DownloadEvent = downloadEvent;
}

那么你可以在方法DidWriteData():

有数据进来的时候触发这个事件
float progress = (float)totalBytesWritten / totalBytesExpectedToWrite;
DownloadEvent(progress);

最后一步是在您的 ViewController 中订阅此活动,例如:

var myViewModel = new ViewModel();
MyViewModel.DownloadEvent += (progress) =>
{
    MyProgress.Progress = progress;
};
myViewModel.downloadTask();