質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

Q&A

解決済

3回答

4619閲覧

【WPF】Rectangleの線の色「Brushes.Red」などを、文字列で指定したい

退会済みユーザー

退会済みユーザー

総合スコア0

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

0グッド

0クリップ

投稿2021/06/18 00:29

いつもお世話になります。
Rectangleの線の色などを、コンボボックスで選んだ値に変更しようと思っています。
色変更は出来るようになったのですが、
Rectangleを動的生成する際にswitch~caseを利用すると、どんどん行数が伸びていき
少々取り扱いがしづらい状況になります。

前提・実現したいこと

コンボボックス(BordColorC)には、Red、BlueなどのStringの値が選択されるようになっており
その値を元に塗りつぶしや線の色を設定したいと思っています。

var MyColor = BordColorC.SelectedItem.ToString();
Rectan.Stroke = Brushes.MyColor;
こんな感じで設定できるのが最適だったのですが、出来ません。
Switchなどで判定していくしか方法はないでしょうか?
何かいい方法はないでしょうか?
昨日一日中調べてましたが、いい方法は見つかりませんでした。
いい方法があれば教えてください。よろしくお願いいたします。

該当のソースコード

//DefaultSetting.xaml <Grid> <Grid.RowDefinitions> <RowDefinition Height="8*"></RowDefinition> <RowDefinition Height="2*"></RowDefinition> </Grid.RowDefinitions> <Rectangle Name="Rectan" VerticalAlignment="Center" HorizontalAlignment="Center" Height="100" Stroke="Black" Width="120" StrokeThickness="2"/> <StackPanel Grid.Row="1" Orientation="Horizontal"> <TextBlock Text="線の色" VerticalAlignment="Center"></TextBlock> <ComboBox Name="BordColorC" ItemsSource= "{StaticResource Colors}" SelectedValue="{Binding DefoBordColor, UpdateSourceTrigger=PropertyChanged}" SelectionChanged="BordColorC_SelectionChanged" Width="50" /> </StackPanel> </Grid>
//DefaultSetting.cs private void BordColorC_SelectionChanged(object sender, SelectionChangedEventArgs e) { var MyColor = BordColorC.SelectedItem.ToString(); switch (MyColor) { case "Red": Rectan.Stroke = Brushes.Red; break; case "Blue": Rectan.Stroke = Brushes.Blue; break; case "Green": Rectan.Stroke = Brushes.Green; break; case "White": Rectan.Stroke = Brushes.White; break; case "Black": Rectan.Stroke = Brushes.Black; break; case "NoColor": Rectan.Stroke = Brushes.Transparent; break; default: break; }
//DefoData.cs public class DefoltData { public static string DefoBordColor { get { return Properties.Settings.Default.DefaBordColor; } set { Properties.Settings.Default.DefaBordColor=value; } } }

試したこと

var MyColor = BordColorC.SelectedItem.ToString(); Rectan.Stroke = Brushes.MyColor;

→もちろん失敗

https://teratail.com/questions/129747
[wpf] drawing.colorからwindows.media.brushへの変換

参考になりそうですが、あまりよく分かっていません。
動作はしそうですが、Switchで判定しないといけないのは
変わりないかなと思っています。確認中です。

補足情報(FW/ツールのバージョンなど)

VisualStudio 2019
.NET 4.5(だったはず)
WPF C# (※ WinFormではない)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

解決されているので蛇足ですが、文字列からBrushへの変換はBrushConverterが用意されています。
BrushConverter クラス (System.Windows.Media) | Microsoft Docs

表示される文字列を日本語にしたり色見本を出したくなったときに、dodox86さんの回答のように辞書等で持っておくと楽なので私もこうしますね。

xml

1<Window 2 x:Class="Questions344646.MainWindow" 3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 5 xmlns:System="clr-namespace:System;assembly=mscorlib" 6 Width="600" 7 Height="400" 8 Background="LightGray"> 9 <Window.Resources> 10 <x:Array x:Key="Colors" Type="System:String"> 11 <System:String>Red</System:String> 12 <System:String>Blue</System:String> 13 <System:String>Green</System:String> 14 <System:String>White</System:String> 15 <System:String>Black</System:String> 16 <System:String>NoColor</System:String> 17 </x:Array> 18 </Window.Resources> 19 <Grid> 20 <Grid.ColumnDefinitions> 21 <ColumnDefinition /> 22 <ColumnDefinition /> 23 </Grid.ColumnDefinitions> 24 25 <GroupBox Header="BrushConverter"> 26 <Grid> 27 <Grid.RowDefinitions> 28 <RowDefinition Height="Auto" /> 29 <RowDefinition /> 30 </Grid.RowDefinitions> 31 <DockPanel> 32 <TextBlock VerticalAlignment="Center" Text="線の色" /> 33 <ComboBox 34 x:Name="BordColorC" 35 Margin="5" 36 ItemsSource="{StaticResource Colors}" 37 SelectedValue="{Binding DefoBordColor}" 38 SelectionChanged="BordColorC_SelectionChanged" /> 39 </DockPanel> 40 <Rectangle 41 Name="Rectan" 42 Grid.Row="1" 43 Width="120" 44 Height="100" 45 Stroke="Black" 46 StrokeThickness="2" /> 47 </Grid> 48 </GroupBox> 49 50 <GroupBox Grid.Column="1" Header="Dictionary"> 51 <Grid> 52 <Grid.RowDefinitions> 53 <RowDefinition Height="Auto" /> 54 <RowDefinition /> 55 </Grid.RowDefinitions> 56 <DockPanel> 57 <TextBlock VerticalAlignment="Center" Text="線の色" /> 58 <ComboBox 59 x:Name="BordColorC2" 60 Margin="5" 61 ItemsSource="{Binding Colors}" 62 SelectedValue="{Binding DefoBordColor2}" 63 SelectedValuePath="Key" 64 SelectionChanged="BordColorC2_SelectionChanged"> 65 <ComboBox.ItemTemplate> 66 <DataTemplate> 67 <DockPanel> 68 <Ellipse 69 Width="16" 70 Height="16" 71 Fill="{Binding Value}" /> 72 <TextBlock 73 Margin="5,0" 74 VerticalAlignment="Center" 75 Text="{Binding Key}" /> 76 </DockPanel> 77 </DataTemplate> 78 </ComboBox.ItemTemplate> 79 </ComboBox> 80 </DockPanel> 81 <Rectangle 82 Name="Rectan2" 83 Grid.Row="1" 84 Width="120" 85 Height="100" 86 Stroke="Black" 87 StrokeThickness="2" /> 88 </Grid> 89 </GroupBox> 90 </Grid> 91</Window>

cs

1using System.Collections.Generic; 2using System.ComponentModel; 3using System.Windows; 4using System.Windows.Controls; 5using System.Windows.Media; 6 7namespace Questions344646 8{ 9 public class DefaultData 10 { 11 public static string DefoBordColor 12 { 13 get => Properties.Settings.Default.DefaBordColor; 14 set => Properties.Settings.Default.DefaBordColor = value; 15 } 16 public static string DefoBordColor2 17 { 18 get => Properties.Settings.Default.DefaBordColor2; 19 set => Properties.Settings.Default.DefaBordColor2 = value; 20 } 21 22 public static Dictionary<string, SolidColorBrush> Colors { get; } = 23 new Dictionary<string, SolidColorBrush> 24 { 25 {"Red", Brushes.Red }, 26 {"Blue", Brushes.Blue }, 27 {"Green", Brushes.Green }, 28 {"白", Brushes.White }, 29 {"黒", Brushes.Black }, 30 {"透明", Brushes.Transparent }, 31 }; 32 } 33 34 public partial class MainWindow : Window 35 { 36 public MainWindow() 37 { 38 InitializeComponent(); 39 40 // xamlから逆算するとこうなっているってこと??(ちょっと変わってますね^^; 41 DataContext = new DefaultData(); 42 } 43 44 protected override void OnClosing(CancelEventArgs e) 45 { 46 Properties.Settings.Default.Save(); 47 } 48 49 private void BordColorC_SelectionChanged(object sender, SelectionChangedEventArgs e) 50 { 51 var name = BordColorC.SelectedItem.ToString(); 52 try 53 { 54 var brush = (SolidColorBrush)new BrushConverter().ConvertFromString(name); 55 Rectan.Stroke = brush; 56 } 57 catch 58 { 59 Rectan.Stroke = Brushes.Transparent; 60 } 61 } 62 63 private void BordColorC2_SelectionChanged(object sender, SelectionChangedEventArgs e) 64 { 65 var pair = (KeyValuePair<string, SolidColorBrush>)BordColorC2.SelectedItem; 66 Rectan2.Stroke = pair.Value; 67 } 68 } 69}

アプリ画像

投稿2021/06/18 16:54

編集2023/07/27 15:39
TN8001

総合スコア9321

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2021/06/21 05:22

TN8001様 いつもありがとうございます! 色々と抜粋しているので、おかしいところがあるかもしれません。 良くないかもしれませんが、ウィンドウ表示の所に 以下のようにRefrashさせてました。 ContentRendered += (s, e) => { Refrash(); }; もしかしたら見当違いのことを言ってるかもしれません。すみません。
TN8001

2021/06/21 10:04

> ContentRendered += (s, e) => { Refrash(); }; > もしかしたら見当違いのことを言ってるかもしれません。すみません。 // xamlから逆算するとこうなっているってこと??(ちょっと変わってますね^^; これへの返信ですかね?? 問題なく動いているのでしたら、あまり気になさらないで結構です^^; 説明が足りなかった気がするので、一応説明させていただきますと、 "{Binding DefoBordColor"} となっていることから、DefaultDataがViewModelなのでしょう。 しかしstaticメンバしかいないクラスを、newするのが何となく違和感を感じただけです^^; DefaultDataを複数個所で共用するためでしたら、このままでいいと思います^^
guest

0

ベストアンサー

文字列でプロパティにアクセスしたい場合はReflectionかdynamicを利用します。

C#

1var type = typeof(Brushes); 2Rectan.Stroke = (Brush)type.GetProperty("Red").GetValue(type);

投稿2021/06/18 02:03

neconekocat

総合スコア443

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2021/06/18 04:35

neconekocat様 回答ありがとうございます。 今あるものをそのまま利用することができ、とても嬉しいです。 問題なく動作しました。 まだそこまで理解できていませんが、 リフレクションについて調べてみようと思います。ありがとうございます!
guest

0

コンボボックス(BordColorC)には、Red、BlueなどのStringの値が選択されるようになっており

その値を元に塗りつぶしや線の色を設定したいと思っています。

恐らくそんなに難しく考えることは無くて、例えば Dictionary<TKey,TValue> クラス を用いて、(string, Brush)のペアを作っておき、文字列に対するブラシを返すようなメソッドを用意しておけば良いと思います。

C#

1private static Dictionary<string, Brush> dict = new Dictionary<string, Brush>() { 2 { "Black", Brushes.Black }, 3 { "White", Brushes.White }, 4 { "Red", Brushes.Red }, 5 { "Green", Brushes.Green }, 6 { "Blue", Brushes.Blue }, 7 // .... 8}; 9 10public static Brush FromString(string s) 11{ 12 return dict[s]; 13} 14

で、例えばRectangleであればrect1.Fill = FromString("Red");のように呼び出せば赤に染まります。"Red"等の文字列部分はもちろんBrushes.Red.ToString()で返される文字列を使っても良いと思います。

投稿2021/06/18 01:41

dodox86

総合スコア9183

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2021/06/18 04:33

dodox86様 回答ありがとうございます。 Dictionaryに入れて参照する場所を変える事で Brushes~~の値として参照することができるんですね。 参考になりました!ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問