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

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

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

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

WPF

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

Q&A

解決済

5回答

2903閲覧

C# WPF あるチェックボックス(A)が押されている状態で他の複数あるチェックボックス(B~D)のいずれか一つを外せば(A)が解除される

---stax---

総合スコア148

C#

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

WPF

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

0グッド

0クリップ

投稿2017/10/06 06:57

表題の件で質問お願いします
現在画面上に
□全直 □1直 □2直 □3直
というチェックボックスが配置されています

①全直を押せば1,2,3直すべてがtrueになり
②1,2,3直すべて押せば全直がtrue
③全直が押されている状態で1,2,3直のいずれか一つを外せば全直が解除される
④1,2,3直すべてのチェックは外せない(最後に外そうとしたチェックボックスの切り替えはできなくする)

現在③の部分が満たせておりません

C#

1private void UnCheckChanged(object sender, RoutedEventArgs e) 2 { 3 if ((this.First.IsChecked == false) && (this.Second.IsChecked == false) && (this.Third.IsChecked == false)) 4 { 5 CheckBox cb = sender as CheckBox; 6 cb.IsChecked = true; 7 8 } 9 this.All.IsChecked = false; 10 11 }

上記のイベントで
this.All.IsChecked = false;
を行うと

C#

1private void AllUnChecked(object sender, RoutedEventArgs e) 2 { 3 4 { 5 this.First.IsChecked = false; 6 this.Second.IsChecked = false; 7 this.Third.IsChecked = false; 8 } 9 }

のイベントが発生し自分で選択した以外のほかの直も消えてしまいます
この状態を回避するにはどう対応すればよいでしょうか

以下全コード

C#

1 private void AllChecked(object sender, RoutedEventArgs e) 2 { 3 4 { 5 this.First.IsChecked = true; 6 this.Second.IsChecked = true; 7 this.Third.IsChecked = true; 8 } 9 } 10 11 private void AllUnChecked(object sender, RoutedEventArgs e) 12 { 13 14 { 15 this.First.IsChecked = false; 16 this.Second.IsChecked = false; 17 this.Third.IsChecked = false; 18 } 19 } 20 21 //First,Second,Thirdの状態が変化した 22 private void CheckChanged(object sender, RoutedEventArgs e) 23 { 24 if((this.First.IsChecked == true) && (this.Second.IsChecked == true) && (this.Third.IsChecked == true)) 25 { 26 this.All.IsChecked = true; 27 28 } 29 30 } 31 32 private void UnCheckChanged(object sender, RoutedEventArgs e) 33 { 34 if ((this.First.IsChecked == false) && (this.Second.IsChecked == false) && (this.Third.IsChecked == false)) 35 { 36 CheckBox cb = sender as CheckBox; 37 cb.IsChecked = true; 38 39 } 40 this.All.IsChecked = false; 41 42 } 43 }

XAML

1 2<Grid Margin="0,0,-8,-3"> 3 4<CheckBox x:Name="First" Content="1直" HorizontalAlignment="Left" Margin="749,105,0,0" VerticalAlignment="Top" Checked="CheckChanged" Unchecked="UnCheckChanged"/> 5 <CheckBox x:Name="Second" Content="2直" HorizontalAlignment="Left" Margin="809,105,0,0" VerticalAlignment="Top" Checked="CheckChanged" Unchecked="UnCheckChanged"/> 6 <CheckBox x:Name="Third" Content="3直" HorizontalAlignment="Left" Margin="873,105,0,0" VerticalAlignment="Top" Checked="CheckChanged" Unchecked="UnCheckChanged"/> 7 <CheckBox x:Name="All" Content="全直" HorizontalAlignment="Left" Margin="630,104,0,0" VerticalAlignment="Top" Checked="AllChecked" Unchecked="AllUnChecked"/> 8 <DataGrid x:Name="dataGrid" HorizontalAlignment="Left" Margin="23,159,0,0" VerticalAlignment="Top" Height="537" Width="966"/> 9 10 11 12 13 </Grid>

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

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

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

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

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

lain

2017/10/06 07:43

全直、123直すべてにチェックが付いている状態の時に、全直のチェックを外したら、123のチェック状態はどうするのですか?
---stax---

2017/10/06 23:21

分かりにくくてすいません。ご指摘の内容ですと、本来1,2,3直共チェックは残すのが普通だと思うのですが、現在私の作った物では全直のチェックが外れた時点で1,2直が解除され、3直はチェックが残ります。仕様④を満たそうとして現在の状態になっています。
guest

回答5

0

回答ではありません。
仕様に絡むことなので何とも言えませんが、通常この手の動きは

1,2,3全てON
⇒全はON

1,2,3全てOFF
⇒全はOFF

1,2,3はONとOFFが混在
⇒全はnull

が一般的だと思うのですが、いかがでしょう

投稿2017/10/06 07:24

ebiryo

総合スコア797

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

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

---stax---

2017/10/06 23:26

ありがとうございます。 trueかfalseでしか記述していないから自分でも分かりにくくなっているのかもしれません。 nullという状態を設けると条件判定もしやすくなる気がするので、もう少し回答頂いた内容を噛み砕いてみます。 ありがとうございます。
guest

0

仕様に違和感を感じたため、ebiryoさんに一票なのですが、自分が感じた違和感について少しコメントしてみます。

以下は全直を3ステートではなく2ステートのチェックボックスとした場合の話です。

「全直」を選択状態にすると「1~3」全てを選択状態にするという点はいいのですが、では「全直」を選択解除するとどう振る舞うべきでしょう?現状では「1~3」全てを解除としています。しかしこれは(4)の仕様と不整合であると思います。

UIの仕様の考え方の一つとして、初期状態が不当状態(何も選択されてない状態)であっても、一旦正当な状態に変化させた後は「不当状態に遷移できないようにする」というポリシーがあると思います。(4)はこのポリシーにそった考え方だと思いますが、「全直」解除時の動作はこのポリシーに従っていません。それなら「全直」解除時には「なにもしない」のがいいかというと、そうするなら「チェックボックス」である意味合いが薄れるのでいっそ「全選択」といった単なるボタンの方がよいという話になってくる気がします。

個人的には不当状態を許容しないか(ただし初期状態だけ不当を許容する場合もある)、あるいは不当状態も許容するかのどちらかに操作ポリシーを統一しておいた方がよいと思います。

投稿2017/10/06 09:11

KSwordOfHaste

総合スコア18394

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

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

---stax---

2017/10/06 23:32

回答ありがとうございます。 仕様通りに形にする事だけ考えていたのでご指摘頂いた内容への理解が浅かったです。 確かに、内容的にも全選択という方が良い気がします。 現状は統一感も何もないので個人的にややこしくなっている部分もあると思うのでもう少し構想を確実にして作成していきます。 ありがとうございます。
guest

0

回答ではありません。

同様の質問を他にも投稿されてます。
しかもここ数日そういう行為を何度か。

答える方もどっちに答えていいか、わからなくなるし、
あとから見る人(同じような疑問を持たれたかた)にも
わかりにくいことではないでしょうか?

そういう行為やめませんか?
質問はあとから編集できることでもありますから。

投稿2017/10/06 17:25

283cks

総合スコア138

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

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

---stax---

2017/10/06 23:11

ご指摘ありがとうございます。 取り組んでいる私からすればひとつひとつ違った内容のつもりでしたが、他の人から見ると同じように見えますね。 なかなか理解が進まない中で時間だけが過ぎて行く不安から投稿頻度も多くなっていましたが今後は内容を見極め活用させて頂きます。 ご指摘ありがとうございます。
guest

0

ベストアンサー

折角WPF使っているのでデータバインドしたほうがいいと思う
あと、https://teratail.com/questions/95244の方は放置になるのかな?

namespaceをWpfApp3になっているけど、その辺は読み替えで対応お願い

MainWindowViewModelクラスを別ファイルで作成
大雑把に書くと、1~3のチェックボックスのON/OFFを保持するプライベートフィールドを用意
1~3のプロパティはgetではフィールドをそのまま返すだけ
setではほかの二つとvalueで全部外れるようならフィールドの値を変更しない
(わかりやすさのためにメッセージの出力を行ってるけど不要なら削除でおk)
全直はgetでは1~3が全部ONならtrueを、一つでもOFFならfalseを返すことで個別のフィールドは持ってない
setは1~3をすべてONに変更するだけ

OnPropertyChangedはnameofで囲んだプロパティの変更イベントを発行することで画面へ取得しなおすようにしてる

あとは画面(XAML)でバインドしてるだけ
XAMLのコードビハインドは一切手を入れてない
なれるとデータバインドでprivateフィールドで状態を保持して、publicプロパティのsetterで変更を管理してgetterで良い感じに取得するようにした方が楽だと思う

ViewModel(MainWindowViewModel.cs)

C#

1using System; 2using System.ComponentModel; 3using System.Threading; 4using System.Threading.Tasks; 5 6namespace WpfApp3 7{ 8 public class MainWindowViewModel: INotifyPropertyChanged 9 { 10 private Boolean 直1 = true; 11 private Boolean 直2 = false; 12 private Boolean 直3 = false; 13 14 private String msg = String.Empty; 15 16 public Boolean 直1 17 { 18 get 19 { 20 return this.直1; 21 } 22 set 23 { 24 if (value || this.直2 || this.直3) 25 { 26 this.直1 = value; 27 OnPropertyChanged(nameof(1)); 28 OnPropertyChanged(nameof(全直)); 29 } 30 else 31 { 32 this.SetMessage("チェックは全部解除できません"); 33 } 34 } 35 } 36 37 public Boolean 直2 38 { 39 get 40 { 41 return this.直2; 42 } 43 set 44 { 45 if (this.直1 || value || this.直3) 46 { 47 this.直2 = value; 48 OnPropertyChanged(nameof(2)); 49 OnPropertyChanged(nameof(全直)); 50 } 51 else 52 { 53 this.SetMessage("チェックは全部解除できません"); 54 } 55 } 56 } 57 58 public Boolean 直3 59 { 60 get 61 { 62 return this.直3; 63 } 64 set 65 { 66 if (this.直1 || this.直2 || value) 67 { 68 this.直3 = value; 69 OnPropertyChanged(nameof(3)); 70 OnPropertyChanged(nameof(全直)); 71 } 72 else 73 { 74 this.SetMessage("チェックは全部解除できません"); 75 } 76 } 77 } 78 79 public Boolean 全直 80 { 81 get 82 { 83 return this.直1 && this.直2 && this.直3; 84 } 85 set 86 { 87 if(this.直1 && this.直2 && this.直3) 88 { 89 this.SetMessage("すでに全部チェック入ってます"); 90 return; 91 } 92 this.直1 = true; 93 this.直2 = true; 94 this.直3 = true; 95 OnPropertyChanged(nameof(1)); 96 OnPropertyChanged(nameof(2)); 97 OnPropertyChanged(nameof(3)); 98 OnPropertyChanged(nameof(全直)); 99 } 100 } 101 102 public String Msg { get { return this.msg; } } 103 104 private async void SetMessage(String Message) 105 { 106 msg = Message; 107 OnPropertyChanged(nameof(Msg)); 108 109 await Task.Run(() => { 110 Thread.Sleep(5000); 111 }); 112 113 msg = String.Empty; 114 OnPropertyChanged(nameof(Msg)); 115 } 116 117 #region INotifyPropertyChanged 118 119 public event PropertyChangedEventHandler PropertyChanged; 120 121 protected virtual void OnPropertyChanged(string propertyName) 122 { 123 PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 124 } 125 126 #endregion 127 128 } 129} 130

XAML(MainWindow.xaml)

XAML

1<Window x:Class="WpfApp3.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 5 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 6 xmlns:local="clr-namespace:WpfApp3" 7 mc:Ignorable="d" 8 Title="MainWindow" Height="350" Width="525"> 9 <Window.DataContext> 10 <local:MainWindowViewModel /> 11 </Window.DataContext> 12 <Grid> 13 <Grid.RowDefinitions> 14 <RowDefinition Height="30"/> 15 <RowDefinition Height="30"/> 16 <RowDefinition Height="30"/> 17 <RowDefinition Height="30"/> 18 <RowDefinition Height="30*"/> 19 </Grid.RowDefinitions> 20 21 <CheckBox IsChecked="{Binding Path=直1, Mode=TwoWay}" Content="1直" Grid.Row="0" /> 22 <CheckBox IsChecked="{Binding Path=直2,Mode=TwoWay}" Content="2直" Grid.Row="1" /> 23 <CheckBox IsChecked="{Binding Path=直3,Mode=TwoWay}" Content="3直" Grid.Row="2" /> 24 <CheckBox IsChecked="{Binding Path=全直,Mode=TwoWay}" Content="全直" Grid.Row="3" /> 25 26 <TextBlock Text="{Binding Path=Msg}" Grid.Row="4" /> 27 28 </Grid> 29</Window> 30

投稿2017/10/06 13:36

len_souko

総合スコア1348

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

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

---stax---

2017/10/06 23:37

ありがとうございます。 バインドを用いた簡単なサンプルは試してみたのですが、実際どういう場面で使えば良いのか全然理解出来ておらず使う事が出来ていませんでした。 頂いたコードは非常に見やすく時間はかかりますが私でも読み取れそうです。 回答を参考にして頂いたコードを試して勉強させて頂きます。 丁寧にありがとうございます。
guest

0

C#

1using System; 2using System.Collections.Generic; 3using System.Linq; 4using System.Text; 5using System.Threading.Tasks; 6using System.Windows; 7using System.Windows.Controls; 8using System.Windows.Data; 9using System.Windows.Documents; 10using System.Windows.Input; 11using System.Windows.Media; 12using System.Windows.Media.Imaging; 13using System.Windows.Navigation; 14using System.Windows.Shapes; 15using System.ComponentModel; 16using Npgsql; 17using System.Data; 18using System.Web; 19using System.Collections.ObjectModel; 20namespace AllStationCounter 21{ 22 /// <summary> 23 /// MainWindow.xaml の相互作用ロジック 24 /// </summary> 25 public partial class MainWindow : Window 26 { 27 28 29 30 public MainWindow() 31 { 32 33 DataTable tb = new DataTable(); 34 //DataTableのインスタンスtbにnameという名前の列を定義 35 36 tb.Columns.Add("name"); 37 //DataTableのインスタンスtbにnameという列を挿入 38 39 InitializeComponent(); 40 var connString = "Server=cpedev27;Port=5432;User Id=test_user;Password=test_user;Database=test_server;"; 41 var conn = new NpgsqlConnection(connString); 42 conn.Open(); 43 44 45 46 47 48 var command = new NpgsqlCommand("select name from lesson2.person", conn); 49 var dataReader = command.ExecuteReader(); 50 51 52 var row1 = tb.NewRow(); 53 //DataTableのインスタンスtbにrow1という行を定義(tbにはname列がある) 54 55 row1["name"] = "全サブライン"; 56 //tbのname列のrow1(name)行のセルに全サブラインを定義 57 58 tb.Rows.Add(row1); 59 //tbのname列のrow1(name)行のセルに全サブラインを挿入(1.1) 60 61 while (dataReader.Read()) 62 { 63 64 var row = tb.NewRow(); 65 //DataTableのインスタンスtbにrowという行を定義(1.2) 66 67 for (int i = 0; i < dataReader.FieldCount; i++) 68 69 { 70 row["name"] = dataReader["name"]; 71 // dataReader["name"]はDBからとってくるデータの為名前は欲しい列と一致させる 72 } 73 74 tb.Rows.Add(row); 75 76 } 77 78 combo.ItemsSource = tb.DefaultView; 79 combo.DisplayMemberPath = "name"; 80 combo.SelectedValuePath = "name"; 81 82 } 83 84 85 86 87 //全直ボタン操作 88 private void AllChecked(object sender, RoutedEventArgs e) 89 { 90 91 { 92 this.First.IsChecked = true; 93 this.Second.IsChecked = true; 94 this.Third.IsChecked = true; 95 } 96 } 97 98 private void AllUnChecked(object sender, RoutedEventArgs e) 99 { 100 // 101 if (!m_isAutoOff) 102 { 103 this.First.IsChecked = false; 104 this.Second.IsChecked = false; 105 this.Third.IsChecked = false; 106 } 107 } 108 109 //First,Second,Thirdの状態が変化した 110 private void CheckChanged(object sender, RoutedEventArgs e) 111 { 112 if((this.First.IsChecked == true) && (this.Second.IsChecked == true) && (this.Third.IsChecked == true)) 113 { 114 this.All.IsChecked = true; 115 116 } 117 118 } 119 120 private bool m_isAutoOff =false; 121 private void UnCheckChanged(object sender, RoutedEventArgs e) 122 { 123 124 125 if ((this.First.IsChecked == false) && (this.Second.IsChecked == false) && (this.Third.IsChecked == false)) 126 { 127 CheckBox cb = sender as CheckBox; 128 cb.IsChecked = true; 129 130 } 131 m_isAutoOff = true; 132 this.All.IsChecked = false; 133 //↑この処理が終わった瞬間にAllUnCheckedイベントに行くためm_isAutoOff = true;(falseのため未実行になる)を使いイベントを走らせないようにする 134 m_isAutoOff = false; 135 } 136 137 138 139 } 140} 141

XAML

1Window x:Class="AllStationCounter.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 5 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 6 xmlns:local="clr-namespace:AllStationCounter" 7 mc:Ignorable="d" 8 Title="MainWindow" Height="746.799" Width="1016.523"> 9 <Grid Margin="0,0,-8,-3"> 10 11 <Border BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Left" Height="50" Margin="23,152,0,0" VerticalAlignment="Top" Width="577"/> 12 <Border BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Left" Height="47" Margin="616,90,0,0" VerticalAlignment="Top" Width="373"/> 13 <Border BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Left" Height="47" Margin="23,90,0,0" VerticalAlignment="Top" Width="577"/> 14 <ComboBox ItemsSource= "{Binding subline}" x:Name="combo" HorizontalAlignment="Left" Margin="103,34,0,0" VerticalAlignment="Top" Width="193" Height="28"/> 15 <Label x:Name="label" Content="サブライン" HorizontalAlignment="Left" Margin="23,34,0,0" VerticalAlignment="Top" Width="100"/> 16 <Label x:Name="label1" Content="検索期間単位" HorizontalAlignment="Left" Margin="23,100,0,0" VerticalAlignment="Top" Width="100"/> 17 <!--Group1--> 18 <RadioButton x:Name="Productiondate" Content="生産日" HorizontalAlignment="Left" Margin="128,105,0,0" VerticalAlignment="Top" GroupName="Group1"/> 19 <RadioButton x:Name="Timeofoccurrence" Content="発生時間" HorizontalAlignment="Left" Margin="198,105,0,0" VerticalAlignment="Top" GroupName="Group1"/> 20 21 <DatePicker DisplayDateStart="1900/01/01" DisplayDateEnd="3000/01/01" SelectedDateFormat="Short" HorizontalAlignment="Left" Margin="283,100,0,0" VerticalAlignment="Top" Width="138" Height="28" /> 22 <DatePicker DisplayDateStart="1900/01/01" DisplayDateEnd="3000/01/01" SelectedDateFormat="Short" HorizontalAlignment="Left" Margin="439,100,0,0" VerticalAlignment="Top" Width="138" Height="28"/> 23 <CheckBox x:Name="First" Content="1直" HorizontalAlignment="Left" Margin="749,105,0,0" VerticalAlignment="Top" Checked="CheckChanged" Unchecked="UnCheckChanged"/> 24 <CheckBox x:Name="Second" Content="2直" HorizontalAlignment="Left" Margin="809,105,0,0" VerticalAlignment="Top" Checked="CheckChanged" Unchecked="UnCheckChanged"/> 25 <CheckBox x:Name="Third" Content="3直" HorizontalAlignment="Left" Margin="873,105,0,0" VerticalAlignment="Top" Checked="CheckChanged" Unchecked="UnCheckChanged"/> 26 <CheckBox x:Name="All" Content="全直" HorizontalAlignment="Left" Margin="630,104,0,0" VerticalAlignment="Top" Checked="AllChecked" Unchecked="AllUnChecked"/> 27 <DataGrid x:Name="dataGrid" HorizontalAlignment="Left" Margin="23,224,0,0" VerticalAlignment="Top" Height="472" Width="966"/> 28 <Label x:Name="Countunit" Content="集計単位" HorizontalAlignment="Left" Margin="23,162,0,0" VerticalAlignment="Top" Width="87"/> 29 30 <!--Group2--> 31 <RadioButton x:Name="radioButton2" Content="生産日" HorizontalAlignment="Left" Margin="128,167,0,0" VerticalAlignment="Top" GroupName="Group2"/> 32 <RadioButton x:Name="radioButton3" Content="生産直" HorizontalAlignment="Left" Margin="198,167,0,0" VerticalAlignment="Top" GroupName="Group2"/> 33 <RadioButton x:Name="radioButton4" Content="時間" HorizontalAlignment="Left" Margin="283,167,0,0" VerticalAlignment="Top" GroupName="Group2"/> 34 35 <Button x:Name="button" Content="検索" HorizontalAlignment="Left" Margin="616,152,0,0" VerticalAlignment="Top" Width="373" Height="50"/> 36 37 38 39 40 </Grid> 41</Window>

投稿2017/10/06 08:06

---stax---

総合スコア148

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問