WPF UserControl:从 viewModel 调用用户控件的 public 方法
WPF UserControl: Invoke usercontrol's public method from viewModel
我在 C#、NET 3.5 和 Visual Studio 2008 中有一个 MVVM WPF 应用程序。
从主应用程序 xaml 我导入了一个用户控件。
这个用户控件有一些public方法,我感兴趣的有两个。
一种启动动画的方法,另一种停止动画的方法。
从代码隐藏 (xaml.cs) 中的视图构造函数,我调用用户控件 public 方法来启动动画以在我将一些数据加载到我的 gridview 中时向用户显示它在列表视图中。加载数据的方法从我的视图模型中调用。
所以现在,当加载任务完成时,我需要调用另一个用户控件 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...">
代码隐藏(xaml.cs):
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();
}
}
然后在您的代码隐藏中,您可以启动一个任务来跟踪 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 取消。这只是一个示例
您可以使用 INotifyPropertyChanged 界面,例如创建一个 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 的 Changed 事件到 Start/Stop 动画。
然后你可以在你的ViewModel中设置bool来开始停止关闭动画
在您看来
更新
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();
}
}
}
}
我在 C#、NET 3.5 和 Visual Studio 2008 中有一个 MVVM WPF 应用程序。
从主应用程序 xaml 我导入了一个用户控件。
这个用户控件有一些public方法,我感兴趣的有两个。
一种启动动画的方法,另一种停止动画的方法。
从代码隐藏 (xaml.cs) 中的视图构造函数,我调用用户控件 public 方法来启动动画以在我将一些数据加载到我的 gridview 中时向用户显示它在列表视图中。加载数据的方法从我的视图模型中调用。
所以现在,当加载任务完成时,我需要调用另一个用户控件 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...">
代码隐藏(xaml.cs):
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();
}
}
然后在您的代码隐藏中,您可以启动一个任务来跟踪 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 取消。这只是一个示例
您可以使用 INotifyPropertyChanged 界面,例如创建一个 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 的 Changed 事件到 Start/Stop 动画。
然后你可以在你的ViewModel中设置bool来开始停止关闭动画 在您看来
更新
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();
}
}
}
}