.net WPF-在触发命令时调用MVVM UserControl的使用者
我想在MVVM模式中创建一个用户控件“JobEditor”来编辑作业: Usercontorl的使用者持有第三方对象“Job”的实例,并希望将该对象传递给用户控件,在用户控件中有一个“保存”按钮,一旦用户单击该按钮,我们需要通知使用者并传回修改后的“Job”对象(而不是viewmodel) 为了避免第三方对象“Job”的依赖性,我计划:.net WPF-在触发命令时调用MVVM UserControl的使用者,.net,wpf,silverlight,mvvm,user-controls,.net,Wpf,Silverlight,Mvvm,User Controls,我想在MVVM模式中创建一个用户控件“JobEditor”来编辑作业: Usercontorl的使用者持有第三方对象“Job”的实例,并希望将该对象传递给用户控件,在用户控件中有一个“保存”按钮,一旦用户单击该按钮,我们需要通知使用者并传回修改后的“Job”对象(而不是viewmodel) 为了避免第三方对象“Job”的依赖性,我计划: 为名为“JobEditorViewModel”的用户控件创建viewmodel 创建JobEditorView以绑定到“JobEditorViewModel”
public partial class JobEditor : UserControl
{
public static readonly RoutedEvent OnSaveEvent = EventManager.RegisterRoutedEvent(SaveEvent,
RoutingStrategy.Bubble, typeof(RoutedEventHandler),typeof(JobEditor));
public event RoutedEventHandler OnSave
{
add { AddHandler(OnSaveEvent, value); }
remove { RemoveHandler(OnSaveEvent, value); }
}
}
public class SaveEventArgs : RoutedEventArgs
{
public Job Job{ get; private set; }
public SaveEventArgs(RoutedEvent routedEvent, object source,Job job):base(routedEvent,source)
{
this.Job = job;
}
}
问题:是否有一种方法可以从Usercontrol的VIEW模型中用参数SaveEventArg来触发这个事件?
如果你认为你的VIEW模型是一个用户无法访问的实现细节,那么在视图中创建一个依赖项属性并将其绑定到VIEWMIDE的属性。在ViewModel中,一旦有了更新的作业对象,只需将其设置为绑定到该依赖项属性的ViewModel属性,并让绑定处理与视图(以及与消费者)的通信,即作业已更新。好的,我相信我理解您的意图:我为您准备了一个示例: 我将在几分钟内用代码示例更新此答案: 你的邪恶消费者:) 公共类消费者 { 公共消费者() { Job=newjobControlViewModel{Name=“DoLaundry”,Consumer=this}; }
public JobControlViewModel Job { get; set; }
public void Do(Job job)
{
// do something...
}
}
ViewModel文件:
public class JobControlViewModel : ViewModelBase
{
private string name;
private string someParam;
private DelegateCommand myCommand;
public string Name
{
get { return name; }
set
{
name = value;
OnPropertyChanged();
}
}
public string SomeParam
{
get { return someParam; }
set
{
someParam = value;
OnPropertyChanged();
}
}
public DelegateCommand MyCommand
{
get
{
if (this.myCommand == null)
{
myCommand = new DelegateCommand(o => this.Consumer.Do(new Job{Name = this.Name, SomeParam = this.SomeParam}));
}
return this.myCommand;
}
private set
{
this.myCommand = value;
OnPropertyChanged();
}
}
public TheEvilConsumer Consumer { get; set; }
}
你的常规工作是:
public class Job
{
public string Name { get; set; }
public string SomeParam { get; set; }
}
以及INotifyPropertyChanged实现:
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
然后是控件:
<Grid>
<StackPanel>
<TextBlock Text="{Binding Name}" />
<TextBox Text="{Binding SomeParam}" />
<Button Content="Create Job" Command="{Binding MyCommand}" />
</StackPanel>
</Grid>
消费者现在只提供一个操作来调用按钮单击后创建的作业
-----编辑-----
不确定您是否在聊天中看到了我的答案:
我做了一点手脚。根据我目前发现的:创建一个自定义控件。在样式中(setter)将作业DP绑定到内部viewmodel.Job,然后根据vm.Name等属性绑定控件中的字段,这些属性返回Job.Name等Props中的值。将命令绑定到vm,如示例中所示。在命令内部,您需要在视图中调用一个方法,以引发使用者订阅的事件。在g调用方法操作(msdn.microsoft.com/en us/…)如果您的整个体系结构是mvvm,那么您可以与“消费者VM”通信。在另一种情况下,您必须了解控件的ViewModel不应对外可见,因此您需要提供控件的DependencyProperty,您的使用者可以绑定到。当它发生更改时,使用者开始处理作业。我无法控制使用者,也不知道他们采用的是什么体系结构如果我在视图中定义了DependencyProperty,有没有办法触发对viewmodel的更改?因为我的视图不知道第三方对象而是视图模型,所以我需要视图模型构造第三方对象,然后再将其传递回ConsumerTanks的Gope!我确信这段代码会起作用。不过,我想找到一个解决方案在您的示例代码中,UserControl的VM必须保存consumer的实例,因此UserControl必须知道consumer(或其接口)这是不好的,从usercontrol我不想知道关于消费者的任何事情,我不想给消费者或usercontrol本身任何限制,任何想法?这只是一个实现细节。在VM中提供一个委托,稍后再调用。我可以在最后更新示例代码,以表明…当然,您也可以向我们展示e松散耦合的通信,如EventAggregation(进程内)或wcf(进程外)…嗨,Gope,我甚至不想让使用者知道UserControl的ViewModel,只想知道视图。基本上我想在视图中定义RoutedEvent(代码隐藏)然后由使用者来听,但是我不知道如何从ViewModel中调用该事件以及转换的“作业”对象作为arg。知道吗?那么你是什么使用者?WPF视图/控件?顺便说一句,如果使用者只知道,你也可以在控件级别提供委托。。。
public DelegateCommand MyCommand
{
get
{
if (this.myCommand == null)
{
myCommand = new DelegateCommand(o => this.NotficationAction(new Job { Name = this.Name, SomeParam = this.SomeParam }));
}
return this.myCommand;
}
private set
{
this.myCommand = value;
OnPropertyChanged();
}
}
public Action<Job> NotficationAction { get; set; }
public TheEvilConsumer()
{
Job = new JobControlViewModel{ Name = "DoLaundry", NotficationAction = job => Do(job)};
}