WPF初学者です。
wpf(MVVM)のItemsControlを使って、動的にボタンを配置しましたが、そのボタンをクリックしても動作しません。
機能の概要は以下となります。
・MVVMで作成しています。
・ボタンクリックの動作はXAML上の「Command」から呼び出しています。
・RelayCommandクラスを作成しています。
・名前と年齢のみのモデルを3人分ItemsControlで表示しており、各Item毎にボタンを1つ配置しています。
・ボタンの動作は全て同じで、固定文のメッセージボックスを表示するだけです。
トップのGrid直下などに問題のボタンを配置すると、メッセージボックスが正常に出ますが、
ItemsControl配下に配置したボタンはメッセージボックスが出力されませんでした。
デバッグしたところ、ItemsControl配下に配置したボタンをクリックしても「RelayCommand」クラスの「Execute」メソッドが呼び出されないところまでは
分かったのですがなぜ呼び出されないまで分かりませんでした。
上記原因及び対応方法、もしくは調べるためのヒントだけでも構いませんので、ご教示の程宜しくお願い致します。
ソースコードは以下となります。
View(Xaml)
1<Window x:Class="WpfApp1.Views.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 5 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 6 xmlns:local="clr-namespace:WpfApp1" 7 mc:Ignorable="d" 8 Title="MainWindow" Height="450" Width="800"> 9 <Grid> 10 <ItemsControl ItemsSource="{Binding TestList}"> 11 <ItemsControl.ItemTemplate> 12 <DataTemplate> 13 <StackPanel> 14 <TextBlock Text="{Binding Name}"></TextBlock> 15 <TextBlock Text="{Binding Age}"></TextBlock> 16 <Button Content="test" Height="30" Width="90" HorizontalAlignment="Left" Command="{Binding ClickOutMsg}"></Button> 17 </StackPanel> 18 </DataTemplate> 19 </ItemsControl.ItemTemplate> 20 </ItemsControl> 21 </Grid> 22</Window>
View(クラス)
1using System.Windows; 2using WpfApp1.ViewModels; 3 4namespace WpfApp1.Views 5{ 6 public partial class MainWindow : Window 7 { 8 public MainWindow() 9 { 10 InitializeComponent(); 11 this.DataContext = new MainViewModel(); 12 } 13 } 14}
ViewModel
1using System; 2using System.Collections.Generic; 3using System.Linq; 4using System.Text; 5using System.Threading.Tasks; 6using System.ComponentModel; 7using System.Windows.Input; 8using System.Collections.ObjectModel; 9using WpfApp1.Models; 10using System.Data; 11using System.Windows; 12using WpfApp1.Common; 13 14namespace WpfApp1.ViewModels 15{ 16 public class MainViewModel: INotifyPropertyChanged 17 { 18 public event PropertyChangedEventHandler PropertyChanged; 19 20 private void NotifyPropertyChanged(string info) 21 { 22 if (PropertyChanged != null) { 23 PropertyChanged(this, new PropertyChangedEventArgs(info)); 24 } 25 } 26 27 public ObservableCollection<Person> TestList { get; set; } 28 29 public ICommand ClickOutMsg { get; set; } 30 31 public MainViewModel() 32 { 33 ClickOutMsg = new RelayCommand(OutMsg); 34 35 TestList = new ObservableCollection<Person>(Enumerable.Range(0, 3).Select(x => new Person() { 36 Name = "tanaka" + x.ToString(), 37 Age = (30 + x) % 50 38 }).ToArray()); 39 } 40 41 private void OutMsg() 42 { 43 MessageBox.Show("test"); 44 } 45 } 46}
Model
1namespace WpfApp1.Models 2{ 3 public class Person 4 { 5 public string Name { get; set; } 6 public int Age { get; set; } 7 } 8}
RelayCommand
1using System; 2using System.Collections.Generic; 3using System.Linq; 4using System.Text; 5using System.Threading.Tasks; 6using System.Windows.Input; 7 8namespace WpfApp1.Common 9{ 10 /// <summary> 11 /// その機能を中継することのみを目的とするコマンド 12 /// デリゲートを呼び出すことにより、他のオブジェクトに対して呼び出します。 13 ///CanExecute メソッドの既定の戻り値は 'true' です。 14 /// <see cref="RaiseCanExecuteChanged"/> は、次の場合は必ず呼び出す必要があります。 15 /// <see cref="CanExecute"/> は、別の値を返すことが予期されます。 16 /// </summary> 17 public class RelayCommand : ICommand 18 { 19 private readonly Action _execute; 20 private readonly Func<bool> _canExecute; 21 22 /// <summary> 23 /// RaiseCanExecuteChanged が呼び出されたときに生成されます。 24 /// </summary> 25 public event EventHandler CanExecuteChanged; 26 27 /// <summary> 28 /// 常に実行可能な新しいコマンドを作成します。 29 /// </summary> 30 /// <param name="execute">実行ロジック。</param> 31 public RelayCommand(Action execute) 32 : this(execute, null) 33 { 34 } 35 36 /// <summary> 37 /// 新しいコマンドを作成します。 38 /// </summary> 39 /// <param name="execute">実行ロジック。</param> 40 /// <param name="canExecute">実行ステータス ロジック。</param> 41 public RelayCommand(Action execute, Func<bool> canExecute) 42 { 43 if (execute == null) 44 throw new ArgumentNullException("execute"); 45 _execute = execute; 46 _canExecute = canExecute; 47 } 48 49 /// <summary> 50 /// 現在の状態でこの <see cref="RelayCommand"/> が実行できるかどうかを判定します。 51 /// </summary> 52 /// <param name="parameter"> 53 /// コマンドによって使用されるデータ。コマンドが、データの引き渡しを必要としない場合、このオブジェクトを null に設定できます。 54 /// </param> 55 /// <returns>このコマンドが実行可能な場合は true、それ以外の場合は false。</returns> 56 public bool CanExecute(object parameter) 57 { 58 return _canExecute == null ? true : _canExecute(); 59 } 60 61 /// <summary> 62 /// 現在のコマンド ターゲットに対して <see cref="RelayCommand"/> を実行します。 63 /// </summary> 64 /// <param name="parameter"> 65 /// コマンドによって使用されるデータ。コマンドが、データの引き渡しを必要としない場合、このオブジェクトを null に設定できます。 66 /// </param> 67 public void Execute(object parameter) 68 { 69 _execute(); 70 } 71 72 /// <summary> 73 /// <see cref="CanExecuteChanged"/> イベントを発生させるために使用されるメソッド 74 /// <see cref="CanExecute"/> の戻り値を表すために 75 /// メソッドが変更されました。 76 /// </summary> 77 public void RaiseCanExecuteChanged() 78 { 79 var handler = CanExecuteChanged; 80 if (handler != null) 81 { 82 handler(this, EventArgs.Empty); 83 } 84 } 85 } 86 87 88 /// <summary> 89 /// 任意の型の引数を1つ受け付けるRelayCommand 90 /// </summary> 91 /// <typeparam name="T"></typeparam> 92 public class RelayCommand<T> : ICommand 93 { 94 private readonly Action<T> _execute; 95 private readonly Func<T, bool> _canExecute; 96 97 /// <summary> 98 /// RaiseCanExecuteChanged が呼び出されたときに生成されます。 99 /// </summary> 100 public event EventHandler CanExecuteChanged; 101 102 /// <summary> 103 /// 常に実行可能な新しいコマンドを作成します。 104 /// </summary> 105 /// <param name="execute">実行ロジック。</param> 106 public RelayCommand(Action<T> execute) 107 : this(execute, null) 108 { 109 } 110 111 /// <summary> 112 /// 新しいコマンドを作成します。 113 /// </summary> 114 /// <param name="execute">実行ロジック。</param> 115 /// <param name="canExecute">実行ステータス ロジック。</param> 116 public RelayCommand(Action<T> execute, Func<T, bool> canExecute) 117 { 118 if (execute == null) 119 throw new ArgumentNullException("execute"); 120 _execute = execute; 121 _canExecute = canExecute; 122 } 123 124 /// <summary> 125 /// 現在の状態でこの <see cref="RelayCommand"/> が実行できるかどうかを判定します。 126 /// </summary> 127 /// <param name="parameter"> 128 /// コマンドによって使用されるデータ。コマンドが、データの引き渡しを必要としない場合、このオブジェクトを null に設定できます。 129 /// </param> 130 /// <returns>このコマンドが実行可能な場合は true、それ以外の場合は false。</returns> 131 public bool CanExecute(object parameter) 132 { 133 return _canExecute == null ? true : _canExecute((T)parameter); 134 } 135 136 /// <summary> 137 /// 現在のコマンド ターゲットに対して <see cref="RelayCommand"/> を実行します。 138 /// </summary> 139 /// <param name="parameter"> 140 /// コマンドによって使用されるデータ。コマンドが、データの引き渡しを必要としない場合、このオブジェクトを null に設定できます。 141 /// </param> 142 public void Execute(object parameter) 143 { 144 _execute((T)parameter); 145 } 146 147 /// <summary> 148 /// <see cref="CanExecuteChanged"/> イベントを発生させるために使用されるメソッド 149 /// <see cref="CanExecute"/> の戻り値を表すために 150 /// メソッドが変更されました。 151 /// </summary> 152 public void RaiseCanExecuteChanged() 153 { 154 var handler = CanExecuteChanged; 155 if (handler != null) 156 { 157 handler(this, EventArgs.Empty); 158 } 159 } 160 } 161} 162

回答3件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。