C#でWPF学習中「ReactiveCollectionとListbox」

C# コンピュータ
C#
WPFでReactiveCollectionのオブジェクトをListboxのデータソースとしてバインドする方法を試してみました。
ReactiveCollectionを使うことでUI側の制約をあまり気にすることなく要素の追加削除移動が出来ることが確認できました。

実行環境

Windows10 2004
dotnet –version 5.0.104
Visual Studio Code
PowerShell 5.1

プロジェクトの作成

mkdir プロジェクト名
cd プロジェクト名
dotnet new wpf
dotnet add package Microsoft.Xaml.Behaviors.Wpf
dotnet add package ReactiveProperty.WPF
code .

ソースコード

ファイル名:MainWindow.xaml

<Window x:Class="WpfSample23Listbox.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:WpfSample23Listbox"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.DataContext>
        <local:MainWindowViewModel />
    </Window.DataContext>
    <Grid>
        <StackPanel Margin="10" >
            <Label>追加項目の選択</Label>
            <ComboBox
                    DisplayMemberPath="Name"
                    SelectedValuePath="Id"
                    SelectedValue="{Binding ItemsSelected.Value}"
                    SelectedIndex="{Binding ItemsSelectedIndex.Value}"
                    ItemsSource="{Binding Items}" />
            <WrapPanel
                Orientation="Horizontal"
                Margin="10">
                <Button Content="追加"
                        Command="{Binding AddCommand}" />
                <Button Content="削除"
                        Command="{Binding RemoveCommand}" />
                <Button Content="上へ"
                        Command="{Binding UpCommand}" />
                <Button Content="下へ"
                        Command="{Binding DownCommand}" />
            </WrapPanel>
            <ListBox
                    DisplayMemberPath="Name"
                    SelectedValuePath="Id"
                    SelectedIndex="{Binding MethodListIndex.Value}"
                    ItemsSource="{Binding MethodList}">
            </ListBox>

        </StackPanel>
    </Grid>
</Window>

ファイル名:MainWindowViewModel.cs

using System;
using System.ComponentModel;
using Reactive.Bindings;

namespace WpfSample23Listbox
{
    public class MainWindowViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;        

        public ReactiveProperty<Guid> ItemsSelected { get; set; } = new ReactiveProperty<Guid>();
        public ReactiveProperty<int> ItemsSelectedIndex { get; set; } = new ReactiveProperty<int>();
        public ReactiveCollection<Item> Items { get; set; } = new ReactiveCollection<Item>();
        public ReactiveProperty<int> MethodListIndex { get; set; } = new ReactiveProperty<int>();
        public ReactiveCollection<Item> MethodList { get; set; } = new ReactiveCollection<Item>();

        public ReactiveCommand AddCommand { get; }
        public ReactiveCommand RemoveCommand { get; }
        public ReactiveCommand UpCommand { get; }
        public ReactiveCommand DownCommand { get; }
        public MainWindowViewModel()
        {
            Items.AddOnScheduler(new Item("ぼかし"));
            Items.AddOnScheduler(new Item("アンシャープマスキング"));
            Items.AddOnScheduler(new Item("ノンローカルミーン"));

            AddCommand = new ReactiveCommand()
                .WithSubscribe(()=>{
                    var name = Items[ItemsSelectedIndex.Value].Name;
                    MethodList.AddOnScheduler(new Item(name));
                });
            
            RemoveCommand = new ReactiveCommand()
                .WithSubscribe(()=>{
                    if (MethodList.Count == 0) return;
                    if (MethodListIndex.Value < 0) return;
                    MethodList.RemoveAtOnScheduler(MethodListIndex.Value);
                });
            
            UpCommand = new ReactiveCommand()
                .WithSubscribe(()=>{
                    if (MethodList.Count <= 1) return;
                    if (MethodListIndex.Value <= 0) return;

                    MethodList.MoveOnScheduler(MethodListIndex.Value, MethodListIndex.Value-1);
                    MethodListIndex.Value -= 1;
                });
            
            DownCommand = new ReactiveCommand()
                .WithSubscribe(()=>{
                    if (MethodList.Count <= 1) return;
                    if (MethodListIndex.Value >= (MethodList.Count-1)) return;

                    MethodList.MoveOnScheduler(MethodListIndex.Value, MethodListIndex.Value+1);
                    MethodListIndex.Value += 1;
                });
        }
    }
}

ファイル名:Item.cs

using System;

namespace WpfSample23Listbox
{
    public class Item
    {
        public string Name {get; set;}
        public Guid Id {get; set;}

        public Item()
        {
            this.Id = Guid.NewGuid();
        }
        public Item(string name) : this()
        {
            this.Name = name;
        }
    }
}

説明

「追加」ボタンを押すとコンボボックスで選択した項目がリストボックスに追加されます。
リストボックスで項目が選択された状態で「削除」ボタンを押すと項目が削除されます。
リストボックスで項目が選択された状態で「上へ」または「下へ」ボタンをおすと項目が上下に移動します。

コメント