简体   繁体   English

从单独类中的另一个方法更新用户控件内的WPF进度条值?

[英]Updating WPF progress bar value inside a user control from another method in a separate class?

I am new to WPF, threading and this concept of separation of UI. 我是WPF,线程和UI分离这一概念的新手。

So here I have a well designed project in which all calculations are done inside a method (eg Command class and Execute method); 因此,这里有一个设计良好的项目,其中所有计算都在一个方法(例如Command类和Execute方法)内完成; and the User Interface comprises several User Controls. 用户界面包括几个用户控件。

Since the calculation take a couple of minutes I think I should use a progress bar which is on MainControl user control class. 由于计算需要花费几分钟,因此我认为我应该使用MainControl用户控件类上的进度条。

So I created this method inside MainControl to update progress bar: 因此,我在MainControl中创建了此方法来更新进度条:

public void SetProgressBar(int Value, int Min = 0, int Max = 100)
{
    if (Value <= Max && Min <= Value)
    {
        StatusProgress.Minimum = Min;
        StatusProgress.Maximum = Max;
        StatusProgress.Dispatcher.Invoke(
            new Action(() => this.StatusProgress.Value = Value),
            System.Windows.Threading.DispatcherPriority.Background);
    }
}

Then I created a reference to MainControl inside Command class: 然后,我在Command类中创建了对MainControl的引用:

private MainControl MainControlRef;

So in different stage of my calculations I can report the progress using: 因此,在计算的不同阶段,我可以使用以下方法报告进度:

MainControlRef.SetProgressBar(10);

This is what I could come up with. 这就是我能想到的。 I think this just doesn't feel right. 我认为这感觉不对。 I would appreciate if you could give me some feed backs. 如果您能给我一些反馈,我将不胜感激。

Beside that I noticed that the progress bar sometime updates and sometime doesn't. 除此之外,我注意到进度条有时会更新而有时不会更新。

Easy using the MVVM pattern, your VM would typically contain the Command Object(research relay command ), and other data needed by the view such as an int to hold progress bar value. 易于使用MVVM模式,您的VM通常包含Command Object(研究中继命令 )以及视图所需的其他数据,例如用于保存进度条值的int。 Your view then binds to this VM so once your command is executing and updating the progress bar value, your view would be updating as well 然后,您的视图将绑定到该VM,因此一旦您的命令执行并更新进度条值,您的视图也将更新

Sample from an old project below, hope it helps 以下旧项目的样本,希望对您有所帮助

  public class LoginViewModel : ViewModelBase
{
    private static ILog Logger = LogManager.GetLogger(typeof(LoginViewModel));

    #region Properties
    private String _title;
    private String _login;
    private String _password;
    private String _validationMessage;
    private bool _displayLoginButton;
    private bool _displayLoginProgressRing;
    private bool _enableInput;
    private bool _displayValidationMessage;


    private ICommand _loginCommand;

    public LoginViewModel()
    {
        DisplayLoginButton = EnableInput = true;
        DisplayLoginProgressRing = DisplayValidationMessage = false;
    }

    public bool DisplayValidationMessage
    {
        get { return _displayValidationMessage; }
        set
        {
            _displayValidationMessage = value;
            RaisePropertyChanged(() => this.DisplayValidationMessage);
        }

    }

    public bool DisplayLoginButton
    {
        get { return _displayLoginButton; }
        set
        {
            _displayLoginButton = value;
            RaisePropertyChanged(() => this.DisplayLoginButton);
        }

    }

    public bool EnableInput
    {
        get { return _enableInput; }
        set
        {
            _enableInput = value;
            RaisePropertyChanged(() => this.EnableInput);
        }

    }

    public bool DisplayLoginProgressRing
    {
        get { return _displayLoginProgressRing; }
        set
        {
            _displayLoginProgressRing = value;
            RaisePropertyChanged(() => this.DisplayLoginProgressRing);
        }

    }

    public String Title
    {
        get
        {
            return _title;
        }
        set
        {
            _title = value;
            RaisePropertyChanged(() => this.Title);
        }
    }

    public String Login
    {
        get
        {
            return _login;
        }
        set
        {
            _login = value;
            RaisePropertyChanged(() => this.Login);
        }
    }

    public String Password
    {
        get
        {
            return _password;
        }
        set
        {
            _password = value;
            RaisePropertyChanged(() => this.Password);
        }
    }

    public String ValidationMessage
    {
        get
        {
            return _validationMessage;
        }
        set
        {
            _validationMessage = value;
            RaisePropertyChanged(() => this.ValidationMessage);
        }
    } 
    #endregion

    #region Commands
    public ICommand LoginCommand
    {
        get
        {
            return _loginCommand ?? (_loginCommand =
                new RelayCommand<object>((param) => ExecuteLoginCommand(param), (param) => CanExecuteLoginCommand(param)));
        }
    }

    private bool CanExecuteLoginCommand(object parameter)
    {
        var paramArray = (object[])parameter;
        if (paramArray == null) return false;
        PasswordBox pb = paramArray[0] as PasswordBox;
        if (pb == null) return false;
        var pwdText = pb.Password;
        return !(String.IsNullOrEmpty(pwdText) && Login != null);
    }

    private void ExecuteLoginCommand(object parameter)
    {
        Logger.InfoFormat("User [{0}] attempting to login", this.Login);

        DisplayLoginButton = false;
        DisplayLoginProgressRing = true;
        EnableInput = false;

        var paramArray = (object[])parameter;
        var pb = paramArray[0] as PasswordBox;
        var loginWindow = paramArray[1] as LoginView;

        if (pb != null)
            Password = pb.Password;

        if (ValidateInput())
        {
            if (SynchronizationContext.Current == null)
                SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
            var curSyncContext = SynchronizationContext.Current;
            bool authenticated = false;
            Task.Factory.StartNew(() =>
            {
                authenticated = CredentialService.Instance.Store(int.Parse(Login), Password);
                Thread.Sleep(1000);
            }).ContinueWith((task) =>
            {
                curSyncContext.Send((param) =>
                {
                    if (authenticated)
                    {
                        Logger.InfoFormat("User [{0}] Authenticated Successfully, Logging In", this.Login);
                        var mainWindow = new MainWindow();
                        mainWindow.Show();
                        loginWindow.Close();
                    }
                    else
                    {
                        Logger.InfoFormat("User [{0}] Failed to Authenticate", this.Login);                            
                        DisplayValidationMessage = true;
                        ValidationMessage = INVALID_CREDENTIALS;
                        DisplayLoginButton = true;
                        DisplayLoginProgressRing = false;
                        EnableInput = true;
                    }
                }, null);

            });
        }
        else
        {
            Logger.InfoFormat("User [{0}] failed input validation", this.Login);
            DisplayValidationMessage = true;
            ValidationMessage = INVALID_INPUT;
            DisplayLoginButton = true;
            DisplayLoginProgressRing = false;
            EnableInput = true;
        }

    } 
    #endregion

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM