Quantcast
Channel: C#タグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 9297

複数あるExpanderを同時に1つしか展開させない

$
0
0

概要

開閉するコントロールなら何でもいいですが、ここでは複数のExpanderがあるとします。
これらを同時に1つしか開かせないようにするとを実現します。
下のような感じですね。
allowonlyonetrue.gif
そんなにわらわら並べないでTabでいいじゃんとかNavigation Railでいいじゃんとかは…まあそうですね。

前提

ReactivePropertyを使います。
Bindingを簡単にするというのもありますが、Pairwiseがあるのでこれを利用します。

実装

IReactivePrpoerty<bool>の配列等を受け取ってストリームに変換し、
trueの数が2以上になったら古い方のtrueをfalseに戻してやるような購読を行います。

Ext.cs
usingReactive.Bindings;usingReactive.Bindings.Extensions;usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Reactive.Linq;namespaceAllowOnlyOneOpen.Extensions{publicstaticclassExt{publicstaticIDisposableAllowOnlyOneTrue(thisIEnumerable<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

ただExpanderが4つ並んでいるだけです。MaterialDesignThemeは見栄えのためだけです。

MainWindow.xml
<Windowx: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><ExpanderHeader="A"IsExpanded="{Binding AIsExpanded.Value, Mode=TwoWay}"><RectangleHeight="100"Fill="Cyan"/></Expander><ExpanderHeader="B"IsExpanded="{Binding BIsExpanded.Value, Mode=TwoWay}"><RectangleHeight="100"Fill="Gray"/></Expander><ExpanderHeader="C"IsExpanded="{Binding CIsExpanded.Value, Mode=TwoWay}"><RectangleHeight="100"Fill="LightGreen"/></Expander><ExpanderHeader="D"IsExpanded="{Binding DIsExpanded.Value, Mode=TwoWay}"><RectangleHeight="100"Fill="Violet"/></Expander></StackPanel></Window>

ViewModel

ViewにBindしているものを配列に放り込んで、先ほど作った拡張メソッドを使います。

MainWindowViewModel.cs
usingAllowOnlyOneOpen.Extensions;usingReactive.Bindings;namespaceAllowOnlyOneOpen.ViewModels{publicclassMainWindowViewModel:ViewModelBase{publicReactivePropertySlim<bool>AIsExpanded{get;}=new();publicReactivePropertySlim<bool>BIsExpanded{get;}=new();publicReactivePropertySlim<bool>CIsExpanded{get;}=new();publicReactivePropertySlim<bool>DIsExpanded{get;}=new();publicMainWindowViewModel(){vargroup=new[]{AIsExpanded,BIsExpanded,CIsExpanded,DIsExpanded};group.AllowOnlyOneTrue();}}}

雑感

RadioButtonのグループ化を真似して添付プロパティにでもした方が楽かもしれない…

ソースコード


Viewing all articles
Browse latest Browse all 9297

Trending Articles