teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

3

見直しキャンペーン中

2023/07/27 13:35

投稿

TN8001
TN8001

スコア10108

answer CHANGED
@@ -1,229 +1,229 @@
1
- > 1)選択が解除できず、ずっとGrayのスタイルが残る
2
-
3
- ~~`MoveCurrentToPosition(-1)`でもすればいいんじゃないですかね?~~
4
- ~~[CollectionView.MoveCurrentToPosition(Int32) メソッド (System.Windows.Data) | Microsoft Docs](https://docs.microsoft.com/ja-jp/dotnet/api/system.windows.data.collectionview.movecurrenttoposition)~~
5
-
6
- [ApplicationCommands.SelectAll プロパティ (System.Windows.Input) | Microsoft Docs](https://docs.microsoft.com/ja-jp/dotnet/api/system.windows.input.applicationcommands.selectall)
7
- との対称性を考えて`RoutedCommand`にしてみました。
8
- `View`で完結するのがいい点ですが、`ViewModel`でどうこうしたい場合は逆に扱いにくいです^^;
9
-
10
- > 2)TextBoxを選択、☑を操作した時に、LightGrayにならない。
11
-
12
- フォーカスが`TextBox`や`CheckBox`に行きますから当然そうなりますね。
13
- `SelectionUnit="Cell"`でいいならこんな感じで行けましたがどうでしょうか。
14
-
15
- 参考
16
- [wpf - DataGrid SelectionUnit=Cell disables all support for a selected row? - Stack Overflow](https://stackoverflow.com/questions/9489041/datagrid-selectionunit-cell-disables-all-support-for-a-selected-row)
17
-
18
- ```xaml
19
- <Window
20
- x:Class="Questions337191.Views.MainWindow"
21
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
22
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
23
- xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
24
- xmlns:v="clr-namespace:Questions337191.Views"
25
- xmlns:vm="clr-namespace:Questions337191.ViewModels"
26
- Width="525"
27
- Height="350">
28
- <Window.DataContext>
29
- <vm:MainWindowViewModel />
30
- </Window.DataContext>
31
- <DockPanel>
32
- <!--
33
- メニューから呼ぶとなぜか激重になる。
34
- 以降ボタンから呼んでもDataGridの左上ボタンでも同じく激重。
35
- 意味が分からないw
36
- -->
37
- <!--<Menu DockPanel.Dock="Top">
38
- <MenuItem Header="編集">
39
- <MenuItem Command="ApplicationCommands.SelectAll" CommandTarget="{Binding ElementName=dataGrid}" />
40
- <MenuItem Command="v:DataGridBehavior.UnselectAll" CommandTarget="{Binding ElementName=dataGrid}" />
41
- </MenuItem>
42
- </Menu>-->
43
- <Grid>
44
- <Grid.RowDefinitions>
45
- <RowDefinition Height="Auto" />
46
- <RowDefinition />
47
- </Grid.RowDefinitions>
48
- <StackPanel Orientation="Horizontal">
49
- <Button
50
- MinWidth="100"
51
- Margin="5"
52
- Command="ApplicationCommands.SelectAll"
53
- CommandTarget="{Binding ElementName=dataGrid}"
54
- Content="すべて選択" />
55
- <Button
56
- MinWidth="100"
57
- Margin="5"
58
- Command="v:DataGridBehavior.UnselectAll"
59
- CommandTarget="{Binding ElementName=dataGrid}"
60
- Content="選択解除" />
61
- </StackPanel>
62
-
63
- <DataGrid
64
- x:Name="dataGrid"
65
- Grid.Row="1"
66
- ItemsSource="{Binding MyList}"
67
- SelectionUnit="Cell">
68
- <b:Interaction.Behaviors>
69
- <v:DataGridBehavior />
70
- </b:Interaction.Behaviors>
71
- <DataGrid.RowStyle>
72
- <Style TargetType="DataGridRow">
73
- <Setter Property="Height" Value="20" />
74
- <Style.Triggers>
75
- <Trigger Property="v:DataGridAttachedProperties.IsCellSelected" Value="True">
76
- <Setter Property="Height" Value="40" />
77
- <Setter Property="Background" Value="Gray" />
78
- </Trigger>
79
- </Style.Triggers>
80
- </Style>
81
- </DataGrid.RowStyle>
82
-
83
- <DataGrid.CellStyle>
84
- <Style TargetType="DataGridCell">
85
- <Style.Triggers>
86
- <Trigger Property="IsSelected" Value="True">
87
- <Setter Property="Background" Value="LightGray" />
88
- <Setter Property="v:DataGridAttachedProperties.IsCellSelected" Value="True" />
89
- </Trigger>
90
- <Trigger Property="IsSelected" Value="False">
91
- <Setter Property="v:DataGridAttachedProperties.IsCellSelected" Value="False" />
92
- </Trigger>
93
- </Style.Triggers>
94
- </Style>
95
- </DataGrid.CellStyle>
96
-
97
- <DataGrid.Columns>
98
- <DataGridTemplateColumn Width="100">
99
- <DataGridTemplateColumn.CellTemplate>
100
- <DataTemplate>
101
- <StackPanel Orientation="Horizontal">
102
- <TextBox Text="コメント" />
103
- <TextBlock Text="○" />
104
- </StackPanel>
105
- </DataTemplate>
106
- </DataGridTemplateColumn.CellTemplate>
107
- </DataGridTemplateColumn>
108
- </DataGrid.Columns>
109
- </DataGrid>
110
- </Grid>
111
- </DockPanel>
112
- </Window>
113
- ```
114
-
115
- ```C#
116
- using Livet;
117
- using System.Collections.ObjectModel;
118
- using System.Linq;
119
-
120
- namespace Questions337191.ViewModels
121
- {
122
- public class MainWindowViewModel : ViewModel
123
- {
124
- public ObservableCollection<Person> MyList { get; }
125
-
126
- public MainWindowViewModel()
127
- {
128
- MyList = new ObservableCollection<Person>(
129
- Enumerable.Range(1, 10_000).Select(i => new Person
130
- {
131
- Name = "田中" + i,
132
- Age = 20 + i,
133
- AuthMember = i % 2 == 0,
134
- }));
135
- }
136
- }
137
-
138
- public class Person
139
- {
140
- public string Name { get; set; }
141
- public int Age { get; set; }
142
- public bool AuthMember { get; set; }
143
- }
144
- }
145
- ```
146
-
147
- ```C#
148
- using Microsoft.Xaml.Behaviors;
149
- using System.Linq;
150
- using System.Windows;
151
- using System.Windows.Controls;
152
- using System.Windows.Input;
153
- using System.Windows.Media;
154
-
155
- namespace Questions337191.Views
156
- {
157
- // [wpf - DataGrid SelectionUnit=Cell disables all support for a selected row? - Stack Overflow](https://stackoverflow.com/questions/9489041/datagrid-selectionunit-cell-disables-all-support-for-a-selected-row)
158
- public static class DataGridAttachedProperties
159
- {
160
- public static bool GetIsCellSelected(DependencyObject obj) => (bool)obj.GetValue(IsCellSelectedProperty);
161
- public static void SetIsCellSelected(DependencyObject obj, bool value) => obj.SetValue(IsCellSelectedProperty, value);
162
- public static readonly DependencyProperty IsCellSelectedProperty
163
- = DependencyProperty.RegisterAttached("IsCellSelected", typeof(bool), typeof(DataGridAttachedProperties),
164
- new UIPropertyMetadata(false, OnIsCellSelectedChanged));
165
- private static void OnIsCellSelectedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
166
- {
167
- if (d is DataGridCell cell)
168
- {
169
- var row = FindVisualParent<DataGridRow>(cell);
170
-
171
- // 同じ行内で複数選択がある状態でそのうち1つを選択し直した場合
172
- // そのセルはCellSelectedChangedが出ない(選択状態は変わらない)ので
173
- // 周りの選択解除だけ伝わってしまいバグる
174
- //row.SetValue(IsCellSelectedProperty, e.NewValue);
175
-
176
- // しかたがないので行内全走査
177
- // 重そうだが100桁くらいなら気にならなかった(1000桁あると数秒止まった^^;
178
- var p = FindVisualParent<DataGridCellsPanel>(cell);
179
- var b = p.Children.Cast<DataGridCell>().Any(x => x.IsSelected);
180
- row.SetValue(IsCellSelectedProperty, b);
181
- }
182
- }
183
-
184
- private static T FindVisualParent<T>(DependencyObject child) where T : DependencyObject
185
- {
186
- var parentObject = VisualTreeHelper.GetParent(child);
187
- if (parentObject == null) return null;
188
- if (parentObject is T parent) return parent;
189
- else return FindVisualParent<T>(parentObject);
190
- }
191
- }
192
-
193
- public class DataGridBehavior : Behavior<DataGrid>
194
- {
195
- public static readonly RoutedUICommand UnselectAll = new RoutedUICommand("選択解除", "UnselectAll", typeof(DataGridBehavior));
196
-
197
- protected override void OnAttached()
198
- {
199
- base.OnAttached();
200
- var commandBinding = new CommandBinding(UnselectAll, Executed);
201
- AssociatedObject.CommandBindings.Add(commandBinding);
202
- }
203
-
204
- protected override void OnDetaching()
205
- {
206
- base.OnDetaching();
207
- AssociatedObject.CommandBindings.Clear();
208
- }
209
-
210
- private void Executed(object target, ExecutedRoutedEventArgs e)
211
- {
212
- if (AssociatedObject.SelectionUnit == DataGridSelectionUnit.FullRow)
213
- AssociatedObject.UnselectAll();
214
- else
215
- AssociatedObject.UnselectAllCells();
216
- e.Handled = true;
217
- }
218
- }
219
- }
220
- ```
221
-
222
- ---
223
-
224
- あれこれいじっていたらいろいろバグを見つけてしまいました^^;
225
-
226
- * `DataGridAttachedProperties`複数選択時未考慮
227
- 回答コードを参照してください。
228
- * `Menu`や`ContextMenu`で`DataGrid`に`SelectAll`を使うと以降激重
1
+ > 1)選択が解除できず、ずっとGrayのスタイルが残る
2
+
3
+ ~~`MoveCurrentToPosition(-1)`でもすればいいんじゃないですかね?~~
4
+ ~~[CollectionView.MoveCurrentToPosition(Int32) メソッド (System.Windows.Data) | Microsoft Docs](https://docs.microsoft.com/ja-jp/dotnet/api/system.windows.data.collectionview.movecurrenttoposition)~~
5
+
6
+ [ApplicationCommands.SelectAll プロパティ (System.Windows.Input) | Microsoft Docs](https://docs.microsoft.com/ja-jp/dotnet/api/system.windows.input.applicationcommands.selectall)
7
+ との対称性を考えて`RoutedCommand`にしてみました。
8
+ Viewで完結するのがいい点ですが、ViewModelでどうこうしたい場合は逆に扱いにくいです^^;
9
+
10
+ > 2)TextBoxを選択、☑を操作した時に、LightGrayにならない。
11
+
12
+ フォーカスが`TextBox`や`CheckBox`に行きますから当然そうなりますね。
13
+ `SelectionUnit="Cell"`でいいならこんな感じで行けましたがどうでしょうか。
14
+
15
+ 参考
16
+ [wpf - DataGrid SelectionUnit=Cell disables all support for a selected row? - Stack Overflow](https://stackoverflow.com/questions/9489041/datagrid-selectionunit-cell-disables-all-support-for-a-selected-row)
17
+
18
+ ```xml
19
+ <Window
20
+ x:Class="Questions337191.Views.MainWindow"
21
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
22
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
23
+ xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
24
+ xmlns:v="clr-namespace:Questions337191.Views"
25
+ xmlns:vm="clr-namespace:Questions337191.ViewModels"
26
+ Width="525"
27
+ Height="350">
28
+ <Window.DataContext>
29
+ <vm:MainWindowViewModel />
30
+ </Window.DataContext>
31
+ <DockPanel>
32
+ <!--
33
+ メニューから呼ぶとなぜか激重になる。
34
+ 以降ボタンから呼んでもDataGridの左上ボタンでも同じく激重。
35
+ 意味が分からないw
36
+ -->
37
+ <!--<Menu DockPanel.Dock="Top">
38
+ <MenuItem Header="編集">
39
+ <MenuItem Command="ApplicationCommands.SelectAll" CommandTarget="{Binding ElementName=dataGrid}" />
40
+ <MenuItem Command="v:DataGridBehavior.UnselectAll" CommandTarget="{Binding ElementName=dataGrid}" />
41
+ </MenuItem>
42
+ </Menu>-->
43
+ <Grid>
44
+ <Grid.RowDefinitions>
45
+ <RowDefinition Height="Auto" />
46
+ <RowDefinition />
47
+ </Grid.RowDefinitions>
48
+ <StackPanel Orientation="Horizontal">
49
+ <Button
50
+ MinWidth="100"
51
+ Margin="5"
52
+ Command="ApplicationCommands.SelectAll"
53
+ CommandTarget="{Binding ElementName=dataGrid}"
54
+ Content="すべて選択" />
55
+ <Button
56
+ MinWidth="100"
57
+ Margin="5"
58
+ Command="v:DataGridBehavior.UnselectAll"
59
+ CommandTarget="{Binding ElementName=dataGrid}"
60
+ Content="選択解除" />
61
+ </StackPanel>
62
+
63
+ <DataGrid
64
+ x:Name="dataGrid"
65
+ Grid.Row="1"
66
+ ItemsSource="{Binding MyList}"
67
+ SelectionUnit="Cell">
68
+ <b:Interaction.Behaviors>
69
+ <v:DataGridBehavior />
70
+ </b:Interaction.Behaviors>
71
+ <DataGrid.RowStyle>
72
+ <Style TargetType="DataGridRow">
73
+ <Setter Property="Height" Value="20" />
74
+ <Style.Triggers>
75
+ <Trigger Property="v:DataGridAttachedProperties.IsCellSelected" Value="True">
76
+ <Setter Property="Height" Value="40" />
77
+ <Setter Property="Background" Value="Gray" />
78
+ </Trigger>
79
+ </Style.Triggers>
80
+ </Style>
81
+ </DataGrid.RowStyle>
82
+
83
+ <DataGrid.CellStyle>
84
+ <Style TargetType="DataGridCell">
85
+ <Style.Triggers>
86
+ <Trigger Property="IsSelected" Value="True">
87
+ <Setter Property="Background" Value="LightGray" />
88
+ <Setter Property="v:DataGridAttachedProperties.IsCellSelected" Value="True" />
89
+ </Trigger>
90
+ <Trigger Property="IsSelected" Value="False">
91
+ <Setter Property="v:DataGridAttachedProperties.IsCellSelected" Value="False" />
92
+ </Trigger>
93
+ </Style.Triggers>
94
+ </Style>
95
+ </DataGrid.CellStyle>
96
+
97
+ <DataGrid.Columns>
98
+ <DataGridTemplateColumn Width="100">
99
+ <DataGridTemplateColumn.CellTemplate>
100
+ <DataTemplate>
101
+ <StackPanel Orientation="Horizontal">
102
+ <TextBox Text="コメント" />
103
+ <TextBlock Text="○" />
104
+ </StackPanel>
105
+ </DataTemplate>
106
+ </DataGridTemplateColumn.CellTemplate>
107
+ </DataGridTemplateColumn>
108
+ </DataGrid.Columns>
109
+ </DataGrid>
110
+ </Grid>
111
+ </DockPanel>
112
+ </Window>
113
+ ```
114
+
115
+ ```cs
116
+ using Livet;
117
+ using System.Collections.ObjectModel;
118
+ using System.Linq;
119
+
120
+ namespace Questions337191.ViewModels
121
+ {
122
+ public class MainWindowViewModel : ViewModel
123
+ {
124
+ public ObservableCollection<Person> MyList { get; }
125
+
126
+ public MainWindowViewModel()
127
+ {
128
+ MyList = new ObservableCollection<Person>(
129
+ Enumerable.Range(1, 10_000).Select(i => new Person
130
+ {
131
+ Name = "田中" + i,
132
+ Age = 20 + i,
133
+ AuthMember = i % 2 == 0,
134
+ }));
135
+ }
136
+ }
137
+
138
+ public class Person
139
+ {
140
+ public string Name { get; set; }
141
+ public int Age { get; set; }
142
+ public bool AuthMember { get; set; }
143
+ }
144
+ }
145
+ ```
146
+
147
+ ```cs
148
+ using Microsoft.Xaml.Behaviors;
149
+ using System.Linq;
150
+ using System.Windows;
151
+ using System.Windows.Controls;
152
+ using System.Windows.Input;
153
+ using System.Windows.Media;
154
+
155
+ namespace Questions337191.Views
156
+ {
157
+ // [wpf - DataGrid SelectionUnit=Cell disables all support for a selected row? - Stack Overflow](https://stackoverflow.com/questions/9489041/datagrid-selectionunit-cell-disables-all-support-for-a-selected-row)
158
+ public static class DataGridAttachedProperties
159
+ {
160
+ public static bool GetIsCellSelected(DependencyObject obj) => (bool)obj.GetValue(IsCellSelectedProperty);
161
+ public static void SetIsCellSelected(DependencyObject obj, bool value) => obj.SetValue(IsCellSelectedProperty, value);
162
+ public static readonly DependencyProperty IsCellSelectedProperty
163
+ = DependencyProperty.RegisterAttached("IsCellSelected", typeof(bool), typeof(DataGridAttachedProperties),
164
+ new UIPropertyMetadata(false, OnIsCellSelectedChanged));
165
+ private static void OnIsCellSelectedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
166
+ {
167
+ if (d is DataGridCell cell)
168
+ {
169
+ var row = FindVisualParent<DataGridRow>(cell);
170
+
171
+ // 同じ行内で複数選択がある状態でそのうち1つを選択し直した場合
172
+ // そのセルはCellSelectedChangedが出ない(選択状態は変わらない)ので
173
+ // 周りの選択解除だけ伝わってしまいバグる
174
+ //row.SetValue(IsCellSelectedProperty, e.NewValue);
175
+
176
+ // しかたがないので行内全走査
177
+ // 重そうだが100桁くらいなら気にならなかった(1000桁あると数秒止まった^^;
178
+ var p = FindVisualParent<DataGridCellsPanel>(cell);
179
+ var b = p.Children.Cast<DataGridCell>().Any(x => x.IsSelected);
180
+ row.SetValue(IsCellSelectedProperty, b);
181
+ }
182
+ }
183
+
184
+ private static T FindVisualParent<T>(DependencyObject child) where T : DependencyObject
185
+ {
186
+ var parentObject = VisualTreeHelper.GetParent(child);
187
+ if (parentObject == null) return null;
188
+ if (parentObject is T parent) return parent;
189
+ else return FindVisualParent<T>(parentObject);
190
+ }
191
+ }
192
+
193
+ public class DataGridBehavior : Behavior<DataGrid>
194
+ {
195
+ public static readonly RoutedUICommand UnselectAll = new RoutedUICommand("選択解除", "UnselectAll", typeof(DataGridBehavior));
196
+
197
+ protected override void OnAttached()
198
+ {
199
+ base.OnAttached();
200
+ var commandBinding = new CommandBinding(UnselectAll, Executed);
201
+ AssociatedObject.CommandBindings.Add(commandBinding);
202
+ }
203
+
204
+ protected override void OnDetaching()
205
+ {
206
+ base.OnDetaching();
207
+ AssociatedObject.CommandBindings.Clear();
208
+ }
209
+
210
+ private void Executed(object target, ExecutedRoutedEventArgs e)
211
+ {
212
+ if (AssociatedObject.SelectionUnit == DataGridSelectionUnit.FullRow)
213
+ AssociatedObject.UnselectAll();
214
+ else
215
+ AssociatedObject.UnselectAllCells();
216
+ e.Handled = true;
217
+ }
218
+ }
219
+ }
220
+ ```
221
+
222
+ ---
223
+
224
+ あれこれいじっていたらいろいろバグを見つけてしまいました^^;
225
+
226
+ * `DataGridAttachedProperties`複数選択時未考慮
227
+ 回答コードを参照してください。
228
+ * `Menu`や`ContextMenu`で`DataGrid`に`SelectAll`を使うと以降激重
229
229
  `SelectAll`だけの(`Style`等をすべてなくして追加コードが一切ない)状態でも再現しますので、WPFのバグっぽいです(意味が分からな過ぎて原因も回避法もわかりません^^;

2

対称性

2021/05/11 08:56

投稿

TN8001
TN8001

スコア10108

answer CHANGED
@@ -4,7 +4,7 @@
4
4
  ~~[CollectionView.MoveCurrentToPosition(Int32) メソッド (System.Windows.Data) | Microsoft Docs](https://docs.microsoft.com/ja-jp/dotnet/api/system.windows.data.collectionview.movecurrenttoposition)~~
5
5
 
6
6
  [ApplicationCommands.SelectAll プロパティ (System.Windows.Input) | Microsoft Docs](https://docs.microsoft.com/ja-jp/dotnet/api/system.windows.input.applicationcommands.selectall)
7
- との対性を考えて`RoutedCommand`にしてみました。
7
+ との対性を考えて`RoutedCommand`にしてみました。
8
8
  `View`で完結するのがいい点ですが、`ViewModel`でどうこうしたい場合は逆に扱いにくいです^^;
9
9
 
10
10
  > 2)TextBoxを選択、☑を操作した時に、LightGrayにならない。

1

RoutedCommand

2021/05/11 08:56

投稿

TN8001
TN8001

スコア10108

answer CHANGED
@@ -1,8 +1,12 @@
1
1
  > 1)選択が解除できず、ずっとGrayのスタイルが残る
2
2
 
3
- `MoveCurrentToPosition(-1)`でもすればいいんじゃないですかね?
3
+ ~~`MoveCurrentToPosition(-1)`でもすればいいんじゃないですかね?~~
4
- [CollectionView.MoveCurrentToPosition(Int32) メソッド (System.Windows.Data) | Microsoft Docs](https://docs.microsoft.com/ja-jp/dotnet/api/system.windows.data.collectionview.movecurrenttoposition)
4
+ ~~[CollectionView.MoveCurrentToPosition(Int32) メソッド (System.Windows.Data) | Microsoft Docs](https://docs.microsoft.com/ja-jp/dotnet/api/system.windows.data.collectionview.movecurrenttoposition)~~
5
5
 
6
+ [ApplicationCommands.SelectAll プロパティ (System.Windows.Input) | Microsoft Docs](https://docs.microsoft.com/ja-jp/dotnet/api/system.windows.input.applicationcommands.selectall)
7
+ との対照性を考えて`RoutedCommand`にしてみました。
8
+ `View`で完結するのがいい点ですが、`ViewModel`でどうこうしたい場合は逆に扱いにくいです^^;
9
+
6
10
  > 2)TextBoxを選択、☑を操作した時に、LightGrayにならない。
7
11
 
8
12
  フォーカスが`TextBox`や`CheckBox`に行きますから当然そうなりますね。
@@ -16,109 +20,119 @@
16
20
  x:Class="Questions337191.Views.MainWindow"
17
21
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
18
22
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
23
+ xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
19
24
  xmlns:v="clr-namespace:Questions337191.Views"
20
25
  xmlns:vm="clr-namespace:Questions337191.ViewModels"
21
26
  Width="525"
22
27
  Height="350">
23
-
24
28
  <Window.DataContext>
25
29
  <vm:MainWindowViewModel />
26
30
  </Window.DataContext>
31
+ <DockPanel>
32
+ <!--
33
+ メニューから呼ぶとなぜか激重になる。
34
+ 以降ボタンから呼んでもDataGridの左上ボタンでも同じく激重。
35
+ 意味が分からないw
36
+ -->
37
+ <!--<Menu DockPanel.Dock="Top">
38
+ <MenuItem Header="編集">
39
+ <MenuItem Command="ApplicationCommands.SelectAll" CommandTarget="{Binding ElementName=dataGrid}" />
40
+ <MenuItem Command="v:DataGridBehavior.UnselectAll" CommandTarget="{Binding ElementName=dataGrid}" />
41
+ </MenuItem>
42
+ </Menu>-->
43
+ <Grid>
44
+ <Grid.RowDefinitions>
45
+ <RowDefinition Height="Auto" />
46
+ <RowDefinition />
47
+ </Grid.RowDefinitions>
48
+ <StackPanel Orientation="Horizontal">
49
+ <Button
50
+ MinWidth="100"
51
+ Margin="5"
52
+ Command="ApplicationCommands.SelectAll"
53
+ CommandTarget="{Binding ElementName=dataGrid}"
54
+ Content="すべて選択" />
55
+ <Button
56
+ MinWidth="100"
57
+ Margin="5"
58
+ Command="v:DataGridBehavior.UnselectAll"
59
+ CommandTarget="{Binding ElementName=dataGrid}"
60
+ Content="選択解除" />
61
+ </StackPanel>
27
62
 
28
- <Grid>
63
+ <DataGrid
64
+ x:Name="dataGrid"
29
- <Grid.RowDefinitions>
65
+ Grid.Row="1"
66
+ ItemsSource="{Binding MyList}"
30
- <RowDefinition Height="50" />
67
+ SelectionUnit="Cell">
68
+ <b:Interaction.Behaviors>
31
- <RowDefinition />
69
+ <v:DataGridBehavior />
70
+ </b:Interaction.Behaviors>
71
+ <DataGrid.RowStyle>
72
+ <Style TargetType="DataGridRow">
32
- <RowDefinition Height="50" />
73
+ <Setter Property="Height" Value="20" />
74
+ <Style.Triggers>
75
+ <Trigger Property="v:DataGridAttachedProperties.IsCellSelected" Value="True">
76
+ <Setter Property="Height" Value="40" />
77
+ <Setter Property="Background" Value="Gray" />
78
+ </Trigger>
79
+ </Style.Triggers>
80
+ </Style>
33
- </Grid.RowDefinitions>
81
+ </DataGrid.RowStyle>
34
82
 
35
- <Button
36
- Width="100"
37
- Margin="5"
38
- HorizontalAlignment="Left"
39
- Command="{Binding UnselectCommand}"
40
- Content="選択解除" />
41
- <DataGrid
42
- Grid.Row="1"
43
- IsSynchronizedWithCurrentItem="True"
44
- ItemsSource="{Binding MyList}"
45
- SelectionUnit="Cell">
46
- <DataGrid.RowStyle>
83
+ <DataGrid.CellStyle>
47
- <Style TargetType="DataGridRow">
84
+ <Style TargetType="DataGridCell">
48
- <Setter Property="Height" Value="20" />
49
- <Style.Triggers>
85
+ <Style.Triggers>
50
- <Trigger Property="v:DataGridAttachedProperties.IsCellSelected" Value="True">
51
- <Setter Property="Height" Value="40" />
86
+ <Trigger Property="IsSelected" Value="True">
52
- <Setter Property="Background" Value="Gray" />
87
+ <Setter Property="Background" Value="LightGray" />
88
+ <Setter Property="v:DataGridAttachedProperties.IsCellSelected" Value="True" />
53
- </Trigger>
89
+ </Trigger>
90
+ <Trigger Property="IsSelected" Value="False">
91
+ <Setter Property="v:DataGridAttachedProperties.IsCellSelected" Value="False" />
92
+ </Trigger>
54
- </Style.Triggers>
93
+ </Style.Triggers>
55
- </Style>
94
+ </Style>
56
- </DataGrid.RowStyle>
95
+ </DataGrid.CellStyle>
57
96
 
58
- <DataGrid.CellStyle>
59
- <Style TargetType="DataGridCell">
60
- <Style.Triggers>
61
- <Trigger Property="IsSelected" Value="True">
62
- <Setter Property="Background" Value="LightGray" />
63
- <Setter Property="v:DataGridAttachedProperties.IsCellSelected" Value="True" />
64
- </Trigger>
65
- <Trigger Property="IsSelected" Value="False">
66
- <Setter Property="v:DataGridAttachedProperties.IsCellSelected" Value="False" />
67
- </Trigger>
68
- </Style.Triggers>
69
- </Style>
70
- </DataGrid.CellStyle>
71
-
72
- <DataGrid.Columns>
97
+ <DataGrid.Columns>
73
- <DataGridTemplateColumn Width="100">
98
+ <DataGridTemplateColumn Width="100">
74
- <DataGridTemplateColumn.CellTemplate>
99
+ <DataGridTemplateColumn.CellTemplate>
75
- <DataTemplate>
100
+ <DataTemplate>
76
- <StackPanel Orientation="Horizontal">
101
+ <StackPanel Orientation="Horizontal">
77
- <TextBox Width="50" Text="コメント" />
102
+ <TextBox Text="コメント" />
78
- <TextBlock Text="○" />
103
+ <TextBlock Text="○" />
79
- </StackPanel>
104
+ </StackPanel>
80
- </DataTemplate>
105
+ </DataTemplate>
81
- </DataGridTemplateColumn.CellTemplate>
106
+ </DataGridTemplateColumn.CellTemplate>
82
- </DataGridTemplateColumn>
107
+ </DataGridTemplateColumn>
83
- </DataGrid.Columns>
108
+ </DataGrid.Columns>
84
- </DataGrid>
109
+ </DataGrid>
85
- </Grid>
110
+ </Grid>
111
+ </DockPanel>
86
112
  </Window>
87
113
  ```
88
114
 
89
115
  ```C#
90
116
  using Livet;
91
- using Livet.Commands;
92
117
  using System.Collections.ObjectModel;
93
118
  using System.Linq;
94
- using System.Windows.Data;
95
- using System.Windows.Input;
96
119
 
97
120
  namespace Questions337191.ViewModels
98
121
  {
99
122
  public class MainWindowViewModel : ViewModel
100
123
  {
101
124
  public ObservableCollection<Person> MyList { get; }
102
- public ICommand UnselectCommand { get; }
103
125
 
104
126
  public MainWindowViewModel()
105
127
  {
106
128
  MyList = new ObservableCollection<Person>(
107
- Enumerable.Range(1, 5).Select(i => new Person
129
+ Enumerable.Range(1, 10_000).Select(i => new Person
108
130
  {
109
131
  Name = "田中" + i,
110
132
  Age = 20 + i,
111
- AuthMember = i % 2 == 0
133
+ AuthMember = i % 2 == 0,
112
134
  }));
113
-
114
- UnselectCommand = new ViewModelCommand(TestButton);
115
135
  }
116
-
117
- public void TestButton()
118
- {
119
- var cv = CollectionViewSource.GetDefaultView(MyList);
120
- cv.MoveCurrentToPosition(-1);
121
- }
122
136
  }
123
137
 
124
138
  public class Person
@@ -131,14 +145,16 @@
131
145
  ```
132
146
 
133
147
  ```C#
134
- // [wpf - DataGrid SelectionUnit=Cell disables all support for a selected row? - Stack Overflow](https://stackoverflow.com/questions/9489041/datagrid-selectionunit-cell-disables-all-support-for-a-selected-row)
135
-
148
+ using Microsoft.Xaml.Behaviors;
149
+ using System.Linq;
136
150
  using System.Windows;
137
151
  using System.Windows.Controls;
152
+ using System.Windows.Input;
138
153
  using System.Windows.Media;
139
154
 
140
155
  namespace Questions337191.Views
141
156
  {
157
+ // [wpf - DataGrid SelectionUnit=Cell disables all support for a selected row? - Stack Overflow](https://stackoverflow.com/questions/9489041/datagrid-selectionunit-cell-disables-all-support-for-a-selected-row)
142
158
  public static class DataGridAttachedProperties
143
159
  {
144
160
  public static bool GetIsCellSelected(DependencyObject obj) => (bool)obj.GetValue(IsCellSelectedProperty);
@@ -151,7 +167,17 @@
151
167
  if (d is DataGridCell cell)
152
168
  {
153
169
  var row = FindVisualParent<DataGridRow>(cell);
170
+
171
+ // 同じ行内で複数選択がある状態でそのうち1つを選択し直した場合
172
+ // そのセルはCellSelectedChangedが出ない(選択状態は変わらない)ので
173
+ // 周りの選択解除だけ伝わってしまいバグる
154
- row.SetValue(IsCellSelectedProperty, e.NewValue);
174
+ //row.SetValue(IsCellSelectedProperty, e.NewValue);
175
+
176
+ // しかたがないので行内全走査
177
+ // 重そうだが100桁くらいなら気にならなかった(1000桁あると数秒止まった^^;
178
+ var p = FindVisualParent<DataGridCellsPanel>(cell);
179
+ var b = p.Children.Cast<DataGridCell>().Any(x => x.IsSelected);
180
+ row.SetValue(IsCellSelectedProperty, b);
155
181
  }
156
182
  }
157
183
 
@@ -163,5 +189,41 @@
163
189
  else return FindVisualParent<T>(parentObject);
164
190
  }
165
191
  }
192
+
193
+ public class DataGridBehavior : Behavior<DataGrid>
194
+ {
195
+ public static readonly RoutedUICommand UnselectAll = new RoutedUICommand("選択解除", "UnselectAll", typeof(DataGridBehavior));
196
+
197
+ protected override void OnAttached()
198
+ {
199
+ base.OnAttached();
200
+ var commandBinding = new CommandBinding(UnselectAll, Executed);
201
+ AssociatedObject.CommandBindings.Add(commandBinding);
202
+ }
203
+
204
+ protected override void OnDetaching()
205
+ {
206
+ base.OnDetaching();
207
+ AssociatedObject.CommandBindings.Clear();
208
+ }
209
+
210
+ private void Executed(object target, ExecutedRoutedEventArgs e)
211
+ {
212
+ if (AssociatedObject.SelectionUnit == DataGridSelectionUnit.FullRow)
213
+ AssociatedObject.UnselectAll();
214
+ else
215
+ AssociatedObject.UnselectAllCells();
216
+ e.Handled = true;
217
+ }
218
+ }
166
219
  }
167
- ```
220
+ ```
221
+
222
+ ---
223
+
224
+ あれこれいじっていたらいろいろバグを見つけてしまいました^^;
225
+
226
+ * `DataGridAttachedProperties`複数選択時未考慮
227
+ 回答コードを参照してください。
228
+ * `Menu`や`ContextMenu`で`DataGrid`に`SelectAll`を使うと以降激重
229
+ `SelectAll`だけの(`Style`等をすべてなくして追加コードが一切ない)状態でも再現しますので、WPFのバグっぽいです(意味が分からな過ぎて原因も回避法もわかりません^^;