Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/lua/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# wpfusercontrol:调用UserControl';viewModel中的公共方法_C#_Wpf_Xaml_Mvvm_User Controls - Fatal编程技术网

C# wpfusercontrol:调用UserControl';viewModel中的公共方法

C# wpfusercontrol:调用UserControl';viewModel中的公共方法,c#,wpf,xaml,mvvm,user-controls,C#,Wpf,Xaml,Mvvm,User Controls,我在C#、NET3.5和VisualStudio2008中有一个MVVMWPF应用程序 我从应用程序主xaml导入一个用户控件 这个用户控件有一些公共方法,有两个我感兴趣 一种方法用于启动动画,另一种方法用于停止动画 从code behind(xaml.cs)中视图的构造函数中,我调用用户控件public方法来启动动画,以便在将一些数据加载到listview中的gridview时向用户显示动画。加载数据的方法称为form my view model 现在,当加载任务完成时,我需要调用另一个用户控

我在C#、NET3.5和VisualStudio2008中有一个MVVMWPF应用程序

我从应用程序主xaml导入一个用户控件

这个用户控件有一些公共方法,有两个我感兴趣

一种方法用于启动动画,另一种方法用于停止动画

从code behind(xaml.cs)中视图的构造函数中,我调用用户控件public方法来启动动画,以便在将一些数据加载到listview中的gridview时向用户显示动画。加载数据的方法称为form my view model

现在,当加载任务完成时,我需要调用另一个用户控件public方法来停止动画,但我不知道如何从视图模型中执行此操作


有什么想法吗?我不能触摸用户控件,因为这不是我的

下面是一些代码

XAML

xmlns:controlProgress="clr-namespace:Common.XAML.Controls.Progress;assembly=Common.XAML"

<controlProgress:Progress x:Name="Progress"  
                        Grid.ZIndex="3" 
                        HorizontalAlignment="Center" 
                        VerticalAlignment="Center" 
                        Width="150"  
                        CustomText="Loading..."> 
查看模型:

    public MyView(ViewModelSession vm)
        : base(vm)
    {            
        InitializeComponent();

        Progress.StartAnimation();
    }
    public MyViewModel(Session session)
        : base(session)
    {            
        this.LoadDataIntoGridView(); 
    }

您可以在视图模型中放置一个布尔属性来跟踪加载是否已完成,之后该属性将设置为true

 public class MyViewModel
    {

        public bool IsLoadComplete { get; set; }
        public MyViewModel()
        {
            this.LoadDataIntoGridView();
        }
    }
然后,在codebehind中,您可以启动一项任务来跟踪DataContext属性中的更改:

 public MyView(MyViewModel vm)
        {
            InitializeComponent();

            Progress.StartAnimation();

            Task.Run(() =>
            {
                var dataContext = DataContext as MyViewModel;
                while (true)
                {
                    if (dataContext.IsLoadComplete)
                        break;
                    Task.Delay(100);
                }
                Dispatcher.BeginInvoke(new Action(() => { Progress.StopAnimation(); }));
            });
        }

您必须使用Dispatcher.BeginInvoke在UI线程中将调用排队。当然,这不是一个现成的生产解决方案。在构建视图之前,您可以提供Datacontext,在这种情况下,您必须重构,还可以跟踪刚刚开始的任务,并且可以使用CancellationToken支持取消。这只是一个示例

您可以在视图模型中放置一个布尔属性来跟踪加载是否已完成,之后该属性将设置为true

 public class MyViewModel
    {

        public bool IsLoadComplete { get; set; }
        public MyViewModel()
        {
            this.LoadDataIntoGridView();
        }
    }
然后,在codebehind中,您可以启动一项任务来跟踪DataContext属性中的更改:

 public MyView(MyViewModel vm)
        {
            InitializeComponent();

            Progress.StartAnimation();

            Task.Run(() =>
            {
                var dataContext = DataContext as MyViewModel;
                while (true)
                {
                    if (dataContext.IsLoadComplete)
                        break;
                    Task.Delay(100);
                }
                Dispatcher.BeginInvoke(new Action(() => { Progress.StopAnimation(); }));
            });
        }
您必须使用Dispatcher.BeginInvoke在UI线程中将调用排队。当然,这不是一个现成的生产解决方案。在构建视图之前,您可以提供Datacontext,在这种情况下,您必须重构,还可以跟踪刚刚开始的任务,并且可以使用CancellationToken支持取消。这只是一个示例

您可以使用该界面,例如创建ViewModelBase

public class ViewModelBase
    : INotifyPropertyChanged
{      
    public event PropertyChangedEventHandler PropertyChanged;  

    private void OnPropertyChanged([CallerMemberName] String propertyName = "")
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
然后将其用于ViewModel并添加属性IsLoading

 public class MyViewModel : ViewModelBase
{            
    private bool _isLoading;

    public bool IsLoading
    {
      get { return _isLoading; }
      set
      {
        if(_isLoading == value) return;
         _isLoading = value;
         OnPropertyChanged();
      }
}
然后在视图代码隐藏中,使用ViewModel的PropertyChanged事件启动/停止动画

然后,可以将ViewModel中的布尔设置为开始-停止关闭动画 在你看来

更新

public class MyView
{
    private readonly MyViewModel _viewModel;

    public MyView(MyViewModel viewModel)
          : base(viewModel)
    {
        InitializeComponent();
        _viewModel = viewModel;
        _viewModel.PropertyChanged +=OnPropertyChanged;
    }

    private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == nameof(MyViewModel.IsLoading))
        {
            if (_viewModel.IsLoading)
            {
                Progress.StartAnimation();
            }
            else
            {
                Progress.StopAnimation();
            }
        }
    }
}
您可以使用该界面,例如创建ViewModelBase

public class ViewModelBase
    : INotifyPropertyChanged
{      
    public event PropertyChangedEventHandler PropertyChanged;  

    private void OnPropertyChanged([CallerMemberName] String propertyName = "")
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
然后将其用于ViewModel并添加属性IsLoading

 public class MyViewModel : ViewModelBase
{            
    private bool _isLoading;

    public bool IsLoading
    {
      get { return _isLoading; }
      set
      {
        if(_isLoading == value) return;
         _isLoading = value;
         OnPropertyChanged();
      }
}
然后在视图代码隐藏中,使用ViewModel的PropertyChanged事件启动/停止动画

然后,可以将ViewModel中的布尔设置为开始-停止关闭动画 在你看来

更新

public class MyView
{
    private readonly MyViewModel _viewModel;

    public MyView(MyViewModel viewModel)
          : base(viewModel)
    {
        InitializeComponent();
        _viewModel = viewModel;
        _viewModel.PropertyChanged +=OnPropertyChanged;
    }

    private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == nameof(MyViewModel.IsLoading))
        {
            if (_viewModel.IsLoading)
            {
                Progress.StartAnimation();
            }
            else
            {
                Progress.StopAnimation();
            }
        }
    }
}

“我不能触摸用户控件,因为这不是我的。”然后你就不走运了,因为视图模型没有对视图的引用,所以它不能直接调用它的任何方法。当我看到那条邪恶的线时,我刚刚发布了我的答案。。。我立即删除了它..将你不能触摸的UC包装在你可以触摸的UC中。然后将VM绑定到外部UC。您可以从外部UC的codebehind对VM中的状态更改做出反应,并对包装好的UC执行任何操作。显示它,隐藏它,调用它的方法,在它的脸上打它,等等。“我不能触摸用户控件,因为这不是我的。”然后你就不走运了,因为视图模型没有对视图的引用,所以它不能直接调用它的任何方法。当我看到那条邪恶的线时,我刚刚发布了我的答案。。。我立即删除了它..将你不能触摸的UC包装在你可以触摸的UC中。然后将VM绑定到外部UC。您可以从外部UC的codebehind对VM中的状态更改做出反应,并对包装好的UC执行任何操作。显示它,隐藏它,调用它的方法,在脸上打它,不管什么。我想他的意思是他不能触摸有意义的控制进度用户控制,在这种情况下是可能的。然而,新的MyViewModel().PropertyChanged+=OnPropertyChanged;不正确,但_viewModel.PropertyChanged+=OnPropertyChanged@Mainpat是的,我的意思是我不能触摸controlProgress用户控件,您的解决方案对我来说很好。谢谢。只有一件事,.NET3.5中不支持OnPropertyChanged方法nameof;)我想他的意思是他不能触摸有意义的控件,在这种情况下是可能的。然而,新的MyViewModel().PropertyChanged+=OnPropertyChanged;不正确,但_viewModel.PropertyChanged+=OnPropertyChanged@Mainpat是的,我的意思是我不能触摸controlProgress用户控件,您的解决方案对我来说很好。谢谢。只有一件事,.NET3.5中不支持OnPropertyChanged方法nameof;)