C# wpfusercontrol:调用UserControl';viewModel中的公共方法
我在C#、NET3.5和VisualStudio2008中有一个MVVMWPF应用程序 我从应用程序主xaml导入一个用户控件 这个用户控件有一些公共方法,有两个我感兴趣 一种方法用于启动动画,另一种方法用于停止动画 从code behind(xaml.cs)中视图的构造函数中,我调用用户控件public方法来启动动画,以便在将一些数据加载到listview中的gridview时向用户显示动画。加载数据的方法称为form my view model 现在,当加载任务完成时,我需要调用另一个用户控件public方法来停止动画,但我不知道如何从视图模型中执行此操作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 现在,当加载任务完成时,我需要调用另一个用户控
有什么想法吗?我不能触摸用户控件,因为这不是我的 下面是一些代码 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;)