WPFの色一覧を取得してComboBoxにBindingで表示、一覧はBrushesからPropertyInfoとGetPropertiesを使って取得
動作の様子
できた
コード
2022WPF/20220616_ComboBox_Colors_Binding/20220616_ComboBox_Colors_Binding at master · gogowaten/2022WPF
MainWindow.xaml
<Window x:Class="_20220616_ComboBox_Colors_Binding.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:_20220616_ComboBox_Colors_Binding" mc:Ignorable="d" Title="MainWindow" Height="500" Width="400"> <Grid> <StackPanel x:Name="MyStackPanel"> <StackPanel.Resources> <Style TargetType="TextBlock"> <Setter Property="Margin" Value="0,10,0,0"/> </Style> </StackPanel.Resources> <TextBlock Text="色だけ表示"/> <ComboBox ItemsSource="{Binding}"> <ComboBox.ItemTemplate> <DataTemplate> <Ellipse Fill="{Binding Value}" Width="20" Height="20"/> </DataTemplate> </ComboBox.ItemTemplate> </ComboBox> <TextBlock Text="色と色名を表示"/> <ComboBox ItemsSource="{Binding}"> <ComboBox.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> <Border Width="20" Background="{Binding Value}" Margin="0,2,4,2"/> <TextBlock Text="{Binding Key}"/> </StackPanel> </DataTemplate> </ComboBox.ItemTemplate> </ComboBox> <TextBox x:Name="MyTextBox1" Text="ComboBoxとBinding" FontSize="18" Margin="20,20,20,0"/> <TextBlock Text="TextBoxのForegroundとBinding"/> <ComboBox ItemsSource="{Binding}" SelectedValuePath="Value" SelectedValue="{Binding ElementName=MyTextBox1, Path=Foreground}"> <ComboBox.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> <Border Width="20" Background="{Binding Value}" Margin="0,2,4,2"/> <TextBlock Text="{Binding Key}"/> </StackPanel> </DataTemplate> </ComboBox.ItemTemplate> </ComboBox> <TextBlock Text="TextBoxのBackgroundとBinding"/> <ComboBox ItemsSource="{Binding}" SelectedValuePath="Value" SelectedValue="{Binding ElementName=MyTextBox1, Path=Background}"> <ComboBox.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> <Border Width="20" Background="{Binding Value}" Margin="0,2,4,2"/> <TextBlock Text="{Binding Key}"/> </StackPanel> </DataTemplate> </ComboBox.ItemTemplate> </ComboBox> <Separator Background="{Binding ElementName=MyComboBox3, Path=SelectedValue}" Margin="20,20,20,0"/> <TextBlock Text="多数要素とComboBoxのSelectedValueをBinding"/> <ComboBox x:Name="MyComboBox3" ItemsSource="{Binding}" SelectedValuePath="Value"> <ComboBox.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> <Border Width="20" Background="{Binding Value}" Margin="0,2,4,2"/> <TextBlock Text="{Binding Key}"/> </StackPanel> </DataTemplate> </ComboBox.ItemTemplate> </ComboBox> <TextBlock Text="textblock" Foreground="{Binding ElementName=MyComboBox3, Path=SelectedValue}"/> <Ellipse Width="80" Height="80" Fill="{Binding ElementName=MyComboBox3,Path=SelectedValue}"/> </StackPanel> </Grid> </Window>
MainWindow.xaml.cs
using System.Collections.Generic; using System.Windows; using System.Windows.Media; namespace _20220616_ComboBox_Colors_Binding { public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); Dictionary<string, Brush>? dict = MakeBrushesDictionary(); MyStackPanel.DataContext = dict; } /// <summary> /// BrushesのBrushと名前一覧を取得 /// </summary> /// <returns></returns> private static Dictionary<string, Brush> MakeBrushesDictionary() { //Brushesの情報(PublicとStaticなプロパティ全部)取得 System.Reflection.PropertyInfo[]? brushInfos = typeof(Brushes).GetProperties( System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static); Dictionary<string, Brush> dict = new(); foreach (var item in brushInfos) { if (item.GetValue(null) is not Brush b) { continue; } dict.Add(item.Name, b); } return dict; } } }
Brushesから取得した色の名前とBrushの一覧を詰め込んだDictionaryを作成するMakeBrushesDictionary
Dictionaryの中の要素を見てみると
KeyプロパティにはString型で色の名前と、ValueプロパティにはBrush型の値が入っている
このDictionaryをComboBoxのItemsSourceにBindingすればいい
ここではXAMLで書いておいたStackPanelのMyStackPanelのDataContextに指定した、14行目
あとはXAMLのほうで設定する
一覧データのDictionaryはMyStackPanelのDataContextに指定したので、MyStackPanelの中のComboBoxにも届いているから、ItemsSourceをBindingに指定すれば完了
あとはデータの要素1件1件の表示の仕方を設定はItemTemplate、今回はEllipse要素で丸を表示するようにした、21行目、塗りつぶしのFillにValueをBindingしている、このValueはDictionaryのValueプロパティのことなので、それに入れておいたBrushがBindingされる
結果
やぶからスティックなルー語はおっさんの嗜み
さっきの色だけのComboBoxに色名を足すだけなので、色名表示用のTextBlockを32行目に付け足しただけ、そのBindingのPathに指定しているKeyはDictionaryのKeyのこと
これで
これで表示はだいたいできた
次はComboBoxで選択した項目と、なにか別の要素とのBinding
TextBoxのForeground(文字色)とBinding
こうしたいときは
こう
さっきの色と色名を表示するだけのComboBoxと違うのは、42と43行目だけ
43行目は普通のBindingで選択された値SelectedValueとTextBoxのBinding
42行目ではComboBoxのSelectedValuePathにValueを指定している、これは選択された項目自体はDictionaryの要素の1つで、その要素はKeyとValueの2つの値が入っている、で、そのどちらの値とBindingさせるのかってのを指定する必要があってValueを指定しているみたい
TextBoxのBackground(背景色)とBinding
さっきのForegroundがBackgroundに変わっただけ
ここまではTextBoxが軸、元、SourceでBindingしているけど、BindingのBindingModeが双方向(たぶん既定値)なのでComboBoxの選択項目を変更してもTextBoxのほうも変化している
今度は逆にComboBoxで選択された項目を軸にBinding
SeparatorのBackground
TextblockのForeground
EllipseのFill
この3つ同時
結果の動作はさっきと同じでComboBoxの項目を変更すると色が変わるのは、これも双方向Bindingだからみたい
ComboBoxの設定ではSelectedValuePathにValueの指定が必要
各要素のBindingのPathにはSelectedValueを指定、似たプロパティでSelectedItemってのがあるけど、これだと色が変わらなかった、Bindingにならない
これ思ったけど、一覧表示で色名いらなくて色だけでいいなら、Dictionaryの代わりに配列やListをComboBoxのItemsSourceにBindingすれば、SelectedValuePathは必要ない?
試したら↓でできた
1種類の値なら配列やListをItemsSourceにBindingする、この場合はSelectedValuePathは必要ない
必要になるのは1要素にKeyとValueの2つのプロパティを持つDictionary型や、もっと多くのプロパティを持つ要素の配列やListのときってことかな
関連記事
次回のWPF記事
前回のWPF記事は昨日
gogowaten.hatenablog.com
3年前
WPFのListBoxでいろいろ、Binding、見た目の変更、横リスト - 午後わてんのブログ
gogowaten.hatenablog.com
このときのとほとんど同じ