동시에 여러 Expander만 확장

개요


개폐 제어라면 뭐든지 가능하지만 여긴 익스팬더가 여럿 있어.
동시에 하나만 열어주는 게 이루어졌어요.
느낌은 다음과 같다.

그냥 대충 넘어가지 말고 탭 같아도 되고 Navigation Rail도 돼.

전제 조건


ReactiveProperty를 사용합니다.
간단한 Binding도 있지만 Pairwise가 있어서 이걸 사용합니다.

이루어지다


IreactivePropoerty의 배열 등을 받아서 흐름으로 변환
실제 수량이 2를 초과하면 오래된 진짜를 가짜 구독으로 복원한다.
Ext.cs
using Reactive.Bindings;
using Reactive.Bindings.Extensions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Linq;

namespace AllowOnlyOneOpen.Extensions
{
    public static class Ext
    {
        public static IDisposable AllowOnlyOneTrue(this IEnumerable<IReactiveProperty<bool>> source)
            => source
            .CombineLatest()
            .Pairwise()
            .Where(x => x.NewItem.SkipWhile(n => !n).Skip(1).Any(n => n)) // コントロールの個数を考えるとCount()を素直に使ってよさそうですね
            .Subscribe(p => p.OldItem
                .Select((v, i) => (v, i))
                .Where(x => x.v)
                .Select(x => source.ElementAt(x.i).Value = false)
                .ToList());
    }
}

View


단지 4개의 Expander가 배열되어 있을 뿐이다.Material Design Theeme은 단지 미관을 위한 것이다.
MainWindow.xml
<Window
    x:Class="AllowOnlyOneOpen.Views.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:md="http://materialdesigninxaml.net/winfx/xaml/themes"
    xmlns:vm="clr-namespace:AllowOnlyOneOpen.ViewModels"
    Title="MainWindow"
    Width="400"
    Height="440"
    d:DataContext="{d:DesignInstance Type=vm:MainWindowViewModel,
                                     IsDesignTimeCreatable=True}"
    Foreground="{StaticResource MaterialDesignDarkForeground}"
    Background="{StaticResource MaterialDesignDarkBackground}"
    mc:Ignorable="d">
    <StackPanel>
        <Expander Header="A" IsExpanded="{Binding AIsExpanded.Value, Mode=TwoWay}">
            <Rectangle Height="100" Fill="Cyan" />
        </Expander>
        <Expander Header="B" IsExpanded="{Binding BIsExpanded.Value, Mode=TwoWay}">
            <Rectangle Height="100" Fill="Gray" />
        </Expander>
        <Expander Header="C" IsExpanded="{Binding CIsExpanded.Value, Mode=TwoWay}">
            <Rectangle Height="100" Fill="LightGreen" />
        </Expander>
        <Expander Header="D" IsExpanded="{Binding DIsExpanded.Value, Mode=TwoWay}">
            <Rectangle Height="100" Fill="Violet" />
        </Expander>
    </StackPanel>
</Window>

ViewModel


뷰에 있는 Bind의 물건을 배열에 넣고 방금 만든 확장 방법을 사용하세요.
MainWindowViewModel.cs
using AllowOnlyOneOpen.Extensions;
using Reactive.Bindings;

namespace AllowOnlyOneOpen.ViewModels
{
    public class MainWindowViewModel : ViewModelBase
    {
        public ReactivePropertySlim<bool> AIsExpanded { get; } = new();
        public ReactivePropertySlim<bool> BIsExpanded { get; } = new();
        public ReactivePropertySlim<bool> CIsExpanded { get; } = new();
        public ReactivePropertySlim<bool> DIsExpanded { get; } = new();

        public MainWindowViewModel()
        {
            var group = new [] { AIsExpanded, BIsExpanded, CIsExpanded, DIsExpanded };
            group.AllowOnlyOneTrue();
        }
    }
}

잡감


RadioButton의 그룹을 모방하여 첨부 파일 속성으로 사용하는 것이 비교적 수월할 수 있습니다...

소스 코드

좋은 웹페이지 즐겨찾기