Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/14.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
.net WPF-在触发命令时调用MVVM UserControl的使用者_.net_Wpf_Silverlight_Mvvm_User Controls - Fatal编程技术网

.net WPF-在触发命令时调用MVVM UserControl的使用者

.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”

我想在MVVM模式中创建一个用户控件“JobEditor”来编辑作业:

Usercontorl的使用者持有第三方对象“Job”的实例,并希望将该对象传递给用户控件,在用户控件中有一个“保存”按钮,一旦用户单击该按钮,我们需要通知使用者并传回修改后的“Job”对象(而不是viewmodel)

为了避免第三方对象“Job”的依赖性,我计划:

  • 为名为“JobEditorViewModel”的用户控件创建viewmodel
  • 创建JobEditorView以绑定到“JobEditorViewModel”
  • 创建映射器类以将第三方对象“Job”转换为“JobEditorViewModel”
  • 到目前为止,一切都很好,但更重要的是,向消费者提供信息的最佳方式是什么?我脑子里唯一的想法是:

    向使用者公开“JobEditorViewModel”,在viewmodel中定义一个命令并将Save按钮绑定到它,在命令处理程序中,我将把viewmodel转换回“Job”对象,并传入一个抽象方法调用“Save”(这将是视图模型中唯一的“public”方法,以避免暴露不必要的信息)。消费者将通过继承“JobEditorViewModel”创建自己的ViewModel,并实现抽象的“Save”方法

    我真的不喜欢这个解决方案

    如果有任何想法,我将不胜感激

    --------------------------------------更多信息-------------

    理想情况下,使用者应该能够在xaml中使用此usercontrol,并将“Save”事件(RoutedEvent)绑定到其自己的ViewModel,“Save”事件的参数应该是更新的“Order”对象,因此在usercontrol的ViewModel中,我定义了一个绑定到视图中的Save按钮的命令,一旦用户单击Save按钮,我想在ViewModel命令中构造作业对象并触发RoutedEvent并将作业对象作为参数传递

    usercontrol的代码隐藏中的事件:

    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)};
    }