在另一个类MVVM中调用RelayCommand

时间:2016-06-17 07:42:13

标签: c# wpf mvvm

我正在项目中使用具有委托访问权限的RelayCommand。这是一个有行为的电话。当我在ViewModel中使用Directly时,它可以正常工作。

但是我想在一个类中传递这个命令以便一般地使用它。行为仍然有效,但没有生命的迹象。

我的ViewModel(工作)中的命令:

LoadCommand = new RelayCommand<object>( new Action<object>(
           obj =>
           {
               if (Busy)
                   return;

               Busy = true;
               System.Threading.ThreadPool.QueueUserWorkItem(
                  delegate
                  {
                      Application.Current.Dispatcher.BeginInvoke(new Action(
                           delegate
                           {
                              // myReference.AddDatas(Mvts);
                              AddMoreItems();
                               Busy = false;
                           }));
                  });
           })); 

我新课程中的命令(不起作用):

public Action<object> LoadCommand(Ref<ObservableCollection<T>> myList)
    {
        return new Action<object>(
         obj =>
         {
             if (Busy)
                 return;

             Busy = true;
             System.Threading.ThreadPool.QueueUserWorkItem(
                delegate
                {
                    Application.Current.Dispatcher.Invoke(new Action(
                         delegate
                         {
                             AddDatas(myList);
                             Busy = false;
                         }));
                });
         }));

使用

进行通话
LoadCommand = new RelayCommand<object>(myReference.LoadCommand(Mvts));

我所知道的是,在订单开头放置断点后,它不会被调用。

对于更多信息,我的行为在datagrid的滚动底部

时调用LoadCommand
 public class ScrollViewerMonitor
{
    public static DependencyProperty AtEndCommandProperty
        = DependencyProperty.RegisterAttached(
            "AtEndCommand", typeof(ICommand),
            typeof(ScrollViewerMonitor),
            new PropertyMetadata(OnAtEndCommandChanged));

    public static ICommand GetAtEndCommand(DependencyObject obj)
    {
        return (ICommand)obj.GetValue(AtEndCommandProperty);
    }

    public static void SetAtEndCommand(DependencyObject obj, ICommand value)
    {
        obj.SetValue(AtEndCommandProperty, value);
    }


    public static void OnAtEndCommandChanged(
        DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        FrameworkElement element = (FrameworkElement)d;
        if (element != null)
        {
            element.Loaded -= element_Loaded;
            element.Loaded += element_Loaded;
        }
    }

    static void element_Loaded(object sender, RoutedEventArgs e)
    {
        FrameworkElement element = (FrameworkElement)sender;
        element.Loaded -= element_Loaded;
        ScrollViewer scrollViewer = FindChildOfType<ScrollViewer>(element);
        if (scrollViewer == null)
        {
            return;
        }

        var dpd = DependencyPropertyDescriptor.FromProperty(ScrollViewer.VerticalOffsetProperty, typeof(ScrollViewer));
        dpd.AddValueChanged(scrollViewer, delegate (object o, EventArgs args)
        {
            bool atBottom = scrollViewer.VerticalOffset
                           >= scrollViewer.ScrollableHeight;
            if (atBottom)
            {
                var atEnd = GetAtEndCommand(element);
                if (atEnd != null)
                {
                    atEnd.Execute(null);
                }
            }
        });
    }

    static T FindChildOfType<T>(DependencyObject root) where T : class
    {
        var queue = new Queue<DependencyObject>();
        queue.Enqueue(root);

        while (queue.Count > 0)
        {
            DependencyObject current = queue.Dequeue();
            for (int i = VisualTreeHelper.GetChildrenCount(current) - 1; 0 <= i; i--)
            {
                var child = VisualTreeHelper.GetChild(current, i);
                var typedChild = child as T;
                if (typedChild != null)
                {
                    return typedChild;
                }
                queue.Enqueue(child);
            }
        }
        return null;
    }
}

尽管在两种情况下都达到了 atEnd.Execute(null);

但是当命令在其他文件中执行以下属性时IsAlive = False

IsAlive = false

当命令直接在VM中执行时IsAlive与我的目标对象

为True

Isalive true

2 个答案:

答案 0 :(得分:1)

这两个是完全不同的,第一个是某种属性,它显示了正确的Command绑定,第二个是返回RelayCommand的方法。我不认为你可以将Command属性绑定到方法。这可能是它无法运作的原因。

答案 1 :(得分:1)

没有机会拨打Command,因为您呼叫的不是viewModel的同一个实例。

要在viewModel中从另一个viewModel执行某些操作(例如,运行您的命令或编辑某些属性),最好使用EventAggregator pattern

在我看来,最好的方法是使用Prism框架的EventAggregator模式。 Prism简化了MVVM模式。但是,如果您没有使用过Prism,可以使用Rachel Lim的教程 - simplified version of EventAggregator pattern by Rachel Lim。我强烈推荐你Rachel Lim的方法。

如果您使用Rachel Lim的教程,那么您应该创建一个公共类:

public static class EventSystem
{...Here Publish and Subscribe methods to event...}

将事件发布到OptionViewModel:

eventAggregator.GetEvent<ChangeStockEvent>().Publish(
    new TickerSymbolSelectedMessage{ StockSymbol = “STOCK0” });

然后您在另一个MainViewModel的构造函数中订阅一个事件:

eventAggregator.GetEvent<ChangeStockEvent>().Subscribe(ShowNews);

public void ShowNews(TickerSymbolSelectedMessage msg)
{
   // Handle Event
}

Rachel Lim的简化方法是我见过的最好的方法。但是,如果要创建大型应用程序,则应阅读this article by Magnus Montinat CSharpcorner with an example