命令将停止执行 [英] Commands stop being executed

查看:120
本文介绍了命令将停止执行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

更新 改变我自己的relay命令帮助。 虽然生根funcs中没有

update changing to my own relay command helped. though rooting the Funcs didn't

大家好,我做一个小MVVM应用程序。它应该采取一个类满 Func键<字符串> 并显示每个执行包含的命令的函数功能:LT按钮列表;串> 并显示他们的回归在另一份名单值。

Hi guys I was making a small MVVM application. It is supposed to take a class full of Func<string> and display a list of buttons each executing a command containing a Func<string> and displaying their return values in another list.

该程序工作正常的首先而是随机的按钮presses它只是停止执行命令后。用户界面仍然响应。这是因为如果绑定打破了。

The program works fine at first but after a random amount of button presses it simply stops executing commands. The UI is still responsive. It is as if the binding broke.

有一个有点太多类,所以我在下面的链接连接整个项目

There are a bit too many classes so I attached the whole project in the following link

http://www.megafileupload.com/en/file/ 403770 / GenericTester-zip.html

相关code:

namespace AdapterTester.ViewModel
{
  public class MainViewModel : ViewModelBase
  {
    public ObservableCollection<ViewableRelayCommand> CommandsList { get; set; }
    public ObservableCollection<string> Log { get; set; }

    /// <summary>
    /// Initializes a new instance of the MainViewModel class.
    /// </summary>
    public MainViewModel()
    {
      CommandsList = new ObservableCollection<ViewableRelayCommand>();
      Log = new ObservableCollection<string>();
      MapCommands();
    }

    /// <summary>
    /// adds a ViewableRelayCommand to the CommandsList
    /// </summary>
    public void Add(Func<string> iCommand, string CommandName, Func<bool> CanExecute = null)
    {
      CommandsList.Add(new ViewableRelayCommand()
      {
        Command = new RelayCommand(() => { Log.Insert(0, "-------------\n" + CommandName  + "\n"  + (iCommand.Invoke())); }),
        CommandName = CommandName
      });
    }

    /// <summary>
    /// For Each Func<string> in TestFunctions create a ViewableRelayCommand
    /// </summary>
    private void MapCommands()
    {
      var target = new TestFunctions();
      var methods = target.GetType().GetMethods().Where(m => m.DeclaringType == typeof(TestFunctions));
      foreach (var method in methods)
      {
        if( (method.ReturnType == typeof(string)) && (method.GetParameters().Length ==0))
        {
          Func<string> func = (Func<string>)Delegate.CreateDelegate(typeof(Func<string>), target, method);
          Add(func, method.Name);
        }
      }
    }
  }

  public class ViewableRelayCommand : ViewModelBase
  {
    public RelayCommand Command { get; set; }

    /// <summary>
    /// The <see cref="CommandName" /> property's name.
    /// </summary>
    public const string CommandNamePropertyName = "CommandName";

    private string _CommandName = "Hello";

    /// <summary>
    /// Sets and gets the CommandName property.
    /// Changes to that property's value raise the PropertyChanged event. 
    /// </summary>
    public string CommandName
    {
      get
      {
        return _CommandName;
      }

      set
      {
        if (_CommandName == value)
        {
          return;
        }

        RaisePropertyChanging(CommandNamePropertyName);
        _CommandName = value;
        RaisePropertyChanged(CommandNamePropertyName);
      }
    }
  }
}

XAML:

XAML:

<Window x:Class="AdapterTester.MainWindow"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      xmlns:ignore="http://www.ignore.com"
      mc:Ignorable="d ignore"
      Width="500"
      Height="300"
      Title="MVVM Light Application"
      DataContext="{Binding Main, Source={StaticResource Locator}}">

  <Window.Resources>
    <ResourceDictionary>
      <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="Skins/MainSkin.xaml" />
      </ResourceDictionary.MergedDictionaries>
      <DataTemplate x:Key="myButtonTemplate">
        <Button Content="{Binding Path=CommandName}" Command="{Binding Path=Command}" Margin="3"></Button>
      </DataTemplate>
    </ResourceDictionary>
  </Window.Resources>

  <Grid>
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="*" />
      <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <ListBox Name="CommandsListBox" Grid.Column="0" 
             ItemsSource="{Binding CommandsList}"
             ItemTemplate="{StaticResource myButtonTemplate}">
    </ListBox>
     <ListBox Name="LogListBox" Grid.Column="1" 
                ItemsSource="{Binding Log}"
    </ListBox>
  </Grid>
</Window>

更新:

答案是改变:

 Command = new RelayCommand(() => { Log.Insert(0, "-------------\n" + CommandName  + "\n"  + (iCommand.Invoke())); }),

要这样的:

List<Action> actions = new List<Action>();
public void Add(Func<string> iCommand, string CommandName, Func<bool> CanExecute = null)
{
    Action act = () => { Log.Insert(0, "-------------\n" + CommandName + "\n" + (iCommand.Invoke())); };
    actions.Add(act);
    CommandsList.Add(new ViewableRelayCommand()
    {
        Command = new RelayCommand(act)
        ,
        CommandName = CommandName
    });
}

由于添加了动作继电器命令,其中的根源并非

because the actions added to relay command where not rooted

推荐答案

它是用RelayCommand从MVVMLight?

Is it using RelayCommand from MVVMLight?

如果是这样,你可以打一个GC的问题。 RelayCommand内部使用的WeakReference其回调。

If so, you could be hitting a GC issue. RelayCommand internally uses a WeakReference to its callbacks.

如果你传递的,这不是在其他地方扎根一个匿名函数,那么它可能会得到清理,当GC运行。

If you're passing in an anon function that's not rooted elsewhere, then it could be getting cleaned up when the GC runs.

在大多数情况下,这不是一个问题,因为func是一个回调到虚拟机和虚拟机本身植根于DataContext的,在ViewModelLocator或其他地方。如果您正在创建函数功能的未尽管扎根,这可能是一个问题。

Most of the time this isn't an issue because the func is a callback to the VM and the VM itself is rooted in the DataContext, the ViewModelLocator or elsewhere. If you're creating Func's that aren't rooted though, it could be an issue.

要铲除这些函数功能的是有一个方式名单,其中,Func键&LT;字符串&GT;&GT; 在你的视图模型,并把它们添加到列表中,同时您创建RelayCommands。

One way to root those Func's would be to have a List<Func<string>> in your ViewModel, and add them to the list at the same time you create the RelayCommands.

这篇关于命令将停止执行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆