XAMLでボタンを動的に配置する

今回はXAMLでボタンを動的に配置するするプログラム制作にポンコツ2人組が挑戦してみました。
コードビハインドで動的に配置しているサンプルプログラムを見かけることはありますが、 XAMLで動的に配置するサンプルはあまり見かけないので挑戦することになりました。 開発環境はVisualStudio2022を使用しました。

※この記事は2025/01/28時点の情報です。

Item.cs
ItemクラスにINotifyPropertyChangedを実装して、IsHighlightedプロパティの変更を通知できるようにします。

using System.ComponentModel;

public class Item : INotifyPropertyChanged
{
    private bool _isHighlighted;

    public string Name { get; set; }
    public int Id { get; set; }

    public bool IsHighlighted
    {
        get => _isHighlighted;
        set
        {
            if (_isHighlighted != value)
            {
                _isHighlighted = value;
                OnPropertyChanged(nameof(IsHighlighted));
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

MainViewModel.cs
Listを持つViewModelを用意します。

using System.Collections.ObjectModel;
using System.ComponentModel;

namespace DynamicButtons
{
    public class MainViewModel : INotifyPropertyChanged
    {
        public ObservableCollection<Item> Items { get; set; }

        public MainViewModel()
        {
            Items = new ObservableCollection<Item>
            {
                new Item { Name = "Button1", Id = 1, IsHighlighted = false },
                new Item { Name = "Button2", Id = 2, IsHighlighted = true },
                new Item { Name = "Button3", Id = 3, IsHighlighted = false }
            };
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }
}

MainWindow.xaml
■ ItemsSourceでデータバインディング
XAMLでItemsControlのItemsSourceにViewModelのItemsコレクションをバインドしています。

■ ボタンのプロパティにバインディング
ボタンのContentやNameプロパティにList内の要素のプロパティをバインドしています。

<Window x:Class="DynamicButtons.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:local="clr-namespace:DynamicButtons"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <local:MainViewModel />
    </Window.DataContext>

    <Grid>
        <ItemsControl ItemsSource="{Binding Items}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Button Content="{Binding Name}" 
                            Margin="5"
                            Click="Button_Click">
                        <Button.Style>
                            <Style TargetType="Button">
                                <Setter Property="Background" Value="LightGray" />
                                <Style.Triggers>
                                    <DataTrigger Binding="{Binding IsHighlighted}" Value="True">
                                        <Setter Property="Background" Value="LightGreen" />
                                    </DataTrigger>
                                </Style.Triggers>
                            </Style>
                        </Button.Style>
                    </Button>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </Grid>
</Window>

MainWindow.xaml.cs
Button_Clickイベントでクリックされたボタンに対応するItemオブジェクトを取得し、IsHighlightedプロパティをトグルします。
クリックしたボタンのIsHighlightedがTrue ↔ Falseに切り替わり、背景色がLightGrayとLightGreenの間で動的に変更されます。
senderがクリックされたボタンのインスタンスになります。そのNameプロパティを取得できます。

using System.Windows;
using System.Windows.Controls;

namespace DynamicButtons
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            if (sender is Button button && button.DataContext is Item item)
            {
                // IsHighlightedプロパティをトグル
                item.IsHighlighted = !item.IsHighlighted;
            }
        }
    }
}

以下がアプリケーションを実行した画面です。何とか実装できているようです!

C#のXAMLでボタンを動的に配置

管理人情報