私は2人のコメンターに同意します。データバインディングがこれを行う方法です。最初は非常に複雑に見えることはわかっていますが、コンバーターとコマンドの優れたライブラリをまとめて取得すると、何度も再利用できます。上記のデータ バインディングの例は次のようになります。
XAML で新しいプロジェクトを作成し、メイン ウィンドウにこのコードを貼り付けます。3 つの列を持つデータ グリッドと、新しい行を追加するボタンを追加するだけです。このウィンドウのデータ コンテキストはそれ自体に設定されていることに注意してください。つまり、クラス MainWindow のプロパティは、デフォルトで {Binding} で公開されます。
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Button Content="Button" HorizontalAlignment="Left" Margin="432,289,0,0" VerticalAlignment="Top" Width="75" Command="{Binding AddCommand}"/>
<DataGrid HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Height="274" Width="497" AutoGenerateColumns="False" ItemsSource="{Binding Items}">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Field1}"/>
<DataGridTextColumn Binding="{Binding Field2}"/>
<DataGridTextColumn Binding="{Binding Field3}"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
MainWindow の分離コードです。バインドできる 2 つのプロパティを作成しました。1 つは行として表示されるものの配列を含む項目で、もう 1 つは別の行を追加するために呼び出すことができるコマンドです。
ここの ObservableCollection には、行が変更されたときにバインディング エンジンに通知するメソッドがあるため、グリッドを自分で更新する必要はありません。
public partial class MainWindow : Window
{
public ObservableCollection<Item> Items
{
get { return (ObservableCollection<Item>)GetValue(ItemsProperty); }
set { SetValue(ItemsProperty, value); }
}
public static readonly DependencyProperty ItemsProperty = DependencyProperty.Register("Items", typeof(ObservableCollection<Item>), typeof(MainWindow), new PropertyMetadata(null));
public SimpleCommand AddCommand
{
get { return (SimpleCommand)GetValue(AddCommandProperty); }
set { SetValue(AddCommandProperty, value); }
}
public static readonly DependencyProperty AddCommandProperty = DependencyProperty.Register("AddCommand", typeof(SimpleCommand), typeof(MainWindow), new PropertyMetadata(null));
public MainWindow()
{
InitializeComponent();
Items = new ObservableCollection<Item>();
AddCommand = new SimpleCommand(para =>
{
string nextNumber = Items.Count.ToString();
Items.Add(new Item() { Field1 = nextNumber, Field2 = nextNumber, Field3 = nextNumber });
});
}
}
Item クラスは、データ グリッド、フィールド 1、2、3 に一致する 3 つのプロパティを持つ非常に単純なクラスです。ここでの依存関係プロパティは、データが変更されたときにグリッドを自分で更新する必要がないことも意味します。
public class Item : DependencyObject
{
public string Field1
{
get { return (string)GetValue(Field1Property); }
set { SetValue(Field1Property, value); }
}
public static readonly DependencyProperty Field1Property = DependencyProperty.Register("Field1", typeof(string), typeof(Item), new PropertyMetadata(null));
public string Field2
{
get { return (string)GetValue(Field2Property); }
set { SetValue(Field2Property, value); }
}
public static readonly DependencyProperty Field2Property = DependencyProperty.Register("Field2", typeof(string), typeof(Item), new PropertyMetadata(null));
public string Field3
{
get { return (string)GetValue(Field3Property); }
set { SetValue(Field3Property, value); }
}
public static readonly DependencyProperty Field3Property = DependencyProperty.Register("Field3", typeof(string), typeof(Item), new PropertyMetadata(null));
}
最後に、コマンド クラスです。これは、すべてのプロジェクトで何度も再利用して、何かをコード ビハインドにリンクすることができます。
public class SimpleCommand : DependencyObject, ICommand
{
readonly Action<object> _execute;
readonly Func<object, bool> _canExecute;
public event EventHandler CanExecuteChanged;
public SimpleCommand(Action<object> execute, Func<object, bool> canExecute = null)
{
_canExecute = canExecute == null ? parmeter => { return true; } : canExecute;
_execute = execute;
}
public virtual void Execute(object parameter)
{
_execute(parameter);
}
public virtual bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute(parameter);
}
}