小さなMVVMアプリケーションを作成しています。でいっぱいのクラスを取り、Func<string>
それぞれがを含むコマンドを実行するボタンのリストをFunc<string>
表示し、それらの戻り値を別のリストに表示することになっています。
プログラムは最初は正常に動作しますが、ボタンをランダムに押すと、コマンドの実行が停止します。UIは引き続き応答します。まるでバインディングが壊れたかのようです。
クラスが少し多すぎるので、次のリンクにプロジェクト全体を添付しました。
http://www.megafileupload.com/en/file/403770/GenericTester-zip.html
関連コード:
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:
<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
});
}
ルート化されていない場所でリレーコマンドに追加されたアクションのため。
update自分のリレーコマンドに変更すると役に立ちました。Funcsを応援することはしませんでしたが。