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

回答編集履歴

1

見直しキャンペーン中

2023/07/26 15:32

投稿

TN8001
TN8001

スコア10111

answer CHANGED
@@ -1,275 +1,276 @@
1
- 気になった点の改善版
2
-
3
- 文字数制限のためテンプレートは派手に削ったので、使用側でのカスタマイズ性はないです。キーボードナビゲーション回りもオミットしています^^;
4
- それでもxamlは元より長くなってしまいましたorz
5
-
6
- 本体部分(`Grid`のところ)は非常に短くなりました。
7
- `MenuModel`もスッキリしたと思いますがどうでしょうか?
8
-
9
- `MenuModels`が`ObservableCollection`なので増減があると想定しましたが、固定数なら`CollectionView`を使うまでもないです。
10
-
11
- 見た目を出来合いので済ませるならxamlの大部分は不要です。
12
- 例えばこういうの↓
13
- [Material Design In XAML Toolkit v3.2 の紹介 - Qiita](https://qiita.com/soi/items/85138760233ca050297e#navigationrail)
14
-
15
-
16
- ```xaml
17
- <Window
18
- x:Class="Questions329889_2.MainWindow"
19
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
20
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
21
- xmlns:local="clr-namespace:Questions329889_2"
22
- Width="23cm"
23
- Height="14.2cm">
24
-
25
- <Window.DataContext>
26
- <local:MainViewModel />
27
- </Window.DataContext>
28
-
29
- <Window.Resources>
30
- <Style x:Key="TabControlSidebarStyle" TargetType="{x:Type TabControl}">
31
- <Setter Property="Template">
32
- <Setter.Value>
33
- <ControlTemplate TargetType="{x:Type TabControl}">
34
- <DockPanel>
35
- <TabPanel Background="Gray" IsItemsHost="True" />
36
- <Border>
37
- <ContentPresenter x:Name="PART_SelectedContentHost" ContentSource="SelectedContent" />
38
- </Border>
39
- </DockPanel>
40
- </ControlTemplate>
41
- </Setter.Value>
42
- </Setter>
43
- </Style>
44
-
45
- <Style x:Key="TabItemSidebarButtonStyle" TargetType="{x:Type TabItem}">
46
- <Setter Property="IsSelected" Value="{Binding IsSelected}" />
47
- <Setter Property="Foreground" Value="White" />
48
- <Setter Property="Background" Value="Gray" />
49
- <Setter Property="Template">
50
- <Setter.Value>
51
- <ControlTemplate TargetType="{x:Type TabItem}">
52
- <Grid>
53
- <Border x:Name="mainBorder" Background="{TemplateBinding Background}">
54
- <Border x:Name="innerBorder" Opacity="0" />
55
- </Border>
56
- <ContentPresenter ContentSource="Header" Focusable="False" />
57
- </Grid>
58
- <ControlTemplate.Triggers>
59
- <DataTrigger Binding="{Binding IsMouseOver, RelativeSource={RelativeSource Self}}" Value="True">
60
- <Setter TargetName="mainBorder" Property="Background" Value="#FFBEE6FD" />
61
- </DataTrigger>
62
- <DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource Self}}" Value="True">
63
- <Setter Property="Foreground" Value="Black" />
64
- <Setter Property="Background" Value="White" />
65
- <Setter TargetName="innerBorder" Property="Opacity" Value="1" />
66
- </DataTrigger>
67
- </ControlTemplate.Triggers>
68
- </ControlTemplate>
69
- </Setter.Value>
70
- </Setter>
71
- </Style>
72
-
73
- <DataTemplate x:Key="SidebarButtonTemplate" DataType="{x:Type local:MenuModel}">
74
- <Border Padding="6,10">
75
- <StackPanel>
76
- <TextBlock
77
- FontFamily="Segoe MDL2 Assets"
78
- FontSize="26pt"
79
- Text="{Binding Icon}"
80
- TextAlignment="Center" />
81
- <TextBlock
82
- FontSize="8pt"
83
- Text="{Binding Title}"
84
- TextAlignment="Center" />
85
- </StackPanel>
86
- </Border>
87
- </DataTemplate>
88
-
89
- <DataTemplate x:Key="HomeContentTemplate" DataType="{x:Type local:MenuModel}">
90
- <ItemsControl ItemsSource="{Binding}">
91
- <ItemsControl.ItemTemplate>
92
- <DataTemplate>
93
- <Button
94
- Width="350"
95
- Height="160"
96
- Margin="5"
97
- Background="#efebe9"
98
- Command="{Binding DataContext.ClickMenu, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}"
99
- CommandParameter="{Binding}">
100
- <Button.Template>
101
- <ControlTemplate TargetType="{x:Type Button}">
102
- <Border
103
- Name="border"
104
- Background="{TemplateBinding Background}"
105
- CornerRadius="10">
106
- <ContentPresenter />
107
- </Border>
108
- <ControlTemplate.Triggers>
109
- <Trigger Property="IsMouseOver" Value="True">
110
- <Setter TargetName="border" Property="Background" Value="#FFBEE6FD" />
111
- </Trigger>
112
- </ControlTemplate.Triggers>
113
- </ControlTemplate>
114
- </Button.Template>
115
- <DockPanel Margin="10">
116
- <StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
117
- <TextBlock
118
- Margin="10,0,10,0"
119
- HorizontalAlignment="Center"
120
- VerticalAlignment="Center"
121
- FontFamily="Segoe MDL2 Assets"
122
- FontSize="18pt"
123
- Text="{Binding Icon}" />
124
- <TextBlock FontSize="18pt" Text="{Binding Title}" />
125
- </StackPanel>
126
- <TextBlock
127
- FontSize="11pt"
128
- Text="{Binding Description}"
129
- TextWrapping="Wrap" />
130
- </DockPanel>
131
- </Button>
132
- </DataTemplate>
133
- </ItemsControl.ItemTemplate>
134
- <ItemsControl.ItemsPanel>
135
- <ItemsPanelTemplate>
136
- <WrapPanel HorizontalAlignment="Center" />
137
- </ItemsPanelTemplate>
138
- </ItemsControl.ItemsPanel>
139
- </ItemsControl>
140
- </DataTemplate>
141
-
142
- <local:HomeContentTemplateSelector x:Key="HomeContentTemplateSelector" Template="{StaticResource HomeContentTemplate}" />
143
-
144
- <DataTemplate x:Key="MenuModelContentTemplate" DataType="{x:Type local:MenuModel}">
145
- <ScrollViewer>
146
- <StackPanel>
147
- <TextBlock
148
- Margin="15"
149
- FontSize="23pt"
150
- Foreground="Gray"
151
- Text="{Binding Title}" />
152
- <ContentPresenter
153
- Margin="15"
154
- Content="{Binding Content}"
155
- ContentTemplateSelector="{StaticResource HomeContentTemplateSelector}" />
156
- </StackPanel>
157
- </ScrollViewer>
158
- </DataTemplate>
159
- </Window.Resources>
160
-
161
- <Grid>
162
- <TabControl
163
- ContentTemplate="{StaticResource MenuModelContentTemplate}"
164
- ItemContainerStyle="{StaticResource TabItemSidebarButtonStyle}"
165
- ItemTemplate="{StaticResource SidebarButtonTemplate}"
166
- ItemsSource="{Binding MenuModels}"
167
- Style="{StaticResource TabControlSidebarStyle}"
168
- TabStripPlacement="Left" />
169
-
170
- <Button
171
- Margin="15"
172
- HorizontalAlignment="Right"
173
- VerticalAlignment="Top"
174
- Command="{Binding AddCommand}"
175
- Content="Add" />
176
- </Grid>
177
- </Window>
178
- ```
179
-
180
- ```C#
181
- using Prism.Commands;
182
- using Prism.Mvvm;
183
- using System.Collections.ObjectModel;
184
- using System.Windows;
185
- using System.Windows.Controls;
186
- using System.Windows.Data;
187
-
188
- namespace Questions329889_2
189
- {
190
- public class HomeContentTemplateSelector : DataTemplateSelector
191
- {
192
- public override DataTemplate SelectTemplate(object item, DependencyObject container)
193
- => item is CollectionView ? Template : null;
194
- public DataTemplate Template { get; set; }
195
- }
196
-
197
- public class MenuModel : BindableBase
198
- {
199
- public string Icon { get; init; }
200
- public string Title { get; init; }
201
- public string Description { get; init; }
202
- public object Content { get; set; }
203
-
204
- public bool IsSelected { get => _IsSelected; set => SetProperty(ref _IsSelected, value); }
205
- private bool _IsSelected;
206
- }
207
-
208
- public class MainViewModel : BindableBase
209
- {
210
- public ObservableCollection<MenuModel> MenuModels { get; }
211
- public DelegateCommand<MenuModel> ClickMenu { get; }
212
- public DelegateCommand AddCommand { get; }
213
-
214
- public MainViewModel()
215
- {
216
- MenuModels = new()
217
- {
218
- new()
219
- {
220
- IsSelected = true,
221
- Icon = "\xE10F",
222
- Title = "HOME",
223
- },
224
- new()
225
- {
226
- Icon = "\xF157",
227
- Title = "CONTENT1",
228
- Description = "CONTENT1 です。ここには、CONTENT1 の説明が入ります。",
229
- Content = "CONTENT1 です。",
230
- },
231
- new()
232
- {
233
- Icon = "\xF158",
234
- Title = "CONTENT2",
235
- Description = "CONTENT2 です。ここには、CONTENT2 の説明が入ります。",
236
- },
237
- new()
238
- {
239
- Icon = "\xF159",
240
- Title = "CONTENT3",
241
- Description = "CONTENT3 です。ここには、CONTENT3 の説明が入ります。",
242
- },
243
- };
244
-
245
- MenuModels[0].Content = new ListCollectionView(MenuModels)
246
- {
247
- Filter = (x) => ((MenuModel)x).Title != "HOME",
248
- };
249
-
250
- ClickMenu = new(x =>
251
- {
252
- foreach (var m in MenuModels)
253
- m.IsSelected = x == m;
254
- });
255
-
256
- AddCommand = new(() =>
257
- {
258
- MenuModels.Add(new()
259
- {
260
- Icon = "\xF159",
261
- Title = $"CONTENT{number}",
262
- Description = $"CONTENT{number} です。ここには、CONTENT{number} の説明が入ります。",
263
- });
264
- number++;
265
- });
266
- }
267
- private int number = 4;
268
- }
269
-
270
- public partial class MainWindow : Window
271
- {
272
- public MainWindow() => InitializeComponent();
273
- }
274
- }
275
- ```
1
+ 気になった点の改善版
2
+
3
+ 文字数制限のためテンプレートは派手に削ったので、使用側でのカスタマイズ性はないです。キーボードナビゲーション回りもオミットしています^^;
4
+ それでもxamlは元より長くなってしまいましたorz
5
+
6
+ 本体部分(`Grid`のところ)は非常に短くなりました。
7
+ `MenuModel`もスッキリしたと思いますがどうでしょうか?
8
+
9
+ `MenuModels`が`ObservableCollection`なので増減があると想定しましたが、固定数なら`CollectionView`を使うまでもないです。
10
+
11
+ 見た目を出来合いので済ませるならxamlの大部分は不要です。
12
+ 例えばこういうの↓
13
+ [Material Design In XAML Toolkit v3.2 の紹介 - Qiita](https://qiita.com/soi/items/85138760233ca050297e#navigationrail)
14
+
15
+
16
+ ```xml
17
+ <Window
18
+ x:Class="Questions329889_2.MainWindow"
19
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
20
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
21
+ xmlns:local="clr-namespace:Questions329889_2"
22
+ Width="23cm"
23
+ Height="14.2cm">
24
+
25
+ <Window.DataContext>
26
+ <local:MainViewModel />
27
+ </Window.DataContext>
28
+
29
+ <Window.Resources>
30
+ <Style x:Key="TabControlSidebarStyle" TargetType="{x:Type TabControl}">
31
+ <Setter Property="Template">
32
+ <Setter.Value>
33
+ <ControlTemplate TargetType="{x:Type TabControl}">
34
+ <DockPanel>
35
+ <TabPanel Background="Gray" IsItemsHost="True" />
36
+ <Border>
37
+ <ContentPresenter x:Name="PART_SelectedContentHost" ContentSource="SelectedContent" />
38
+ </Border>
39
+ </DockPanel>
40
+ </ControlTemplate>
41
+ </Setter.Value>
42
+ </Setter>
43
+ </Style>
44
+
45
+ <Style x:Key="TabItemSidebarButtonStyle" TargetType="{x:Type TabItem}">
46
+ <Setter Property="IsSelected" Value="{Binding IsSelected}" />
47
+ <Setter Property="Foreground" Value="White" />
48
+ <Setter Property="Background" Value="Gray" />
49
+ <Setter Property="Template">
50
+ <Setter.Value>
51
+ <ControlTemplate TargetType="{x:Type TabItem}">
52
+ <Grid>
53
+ <Border x:Name="mainBorder" Background="{TemplateBinding Background}">
54
+ <Border x:Name="innerBorder" Opacity="0" />
55
+ </Border>
56
+ <ContentPresenter ContentSource="Header" Focusable="False" />
57
+ </Grid>
58
+ <ControlTemplate.Triggers>
59
+ <DataTrigger Binding="{Binding IsMouseOver, RelativeSource={RelativeSource Self}}" Value="True">
60
+ <Setter TargetName="mainBorder" Property="Background" Value="#FFBEE6FD" />
61
+ </DataTrigger>
62
+ <DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource Self}}" Value="True">
63
+ <Setter Property="Foreground" Value="Black" />
64
+ <Setter Property="Background" Value="White" />
65
+ <Setter TargetName="innerBorder" Property="Opacity" Value="1" />
66
+ </DataTrigger>
67
+ </ControlTemplate.Triggers>
68
+ </ControlTemplate>
69
+ </Setter.Value>
70
+ </Setter>
71
+ </Style>
72
+
73
+ <DataTemplate x:Key="SidebarButtonTemplate" DataType="{x:Type local:MenuModel}">
74
+ <Border Padding="6,10">
75
+ <StackPanel>
76
+ <TextBlock
77
+ FontFamily="Segoe MDL2 Assets"
78
+ FontSize="26pt"
79
+ Text="{Binding Icon}"
80
+ TextAlignment="Center" />
81
+ <TextBlock
82
+ FontSize="8pt"
83
+ Text="{Binding Title}"
84
+ TextAlignment="Center" />
85
+ </StackPanel>
86
+ </Border>
87
+ </DataTemplate>
88
+
89
+ <DataTemplate x:Key="HomeContentTemplate" DataType="{x:Type local:MenuModel}">
90
+ <ItemsControl ItemsSource="{Binding}">
91
+ <ItemsControl.ItemTemplate>
92
+ <DataTemplate>
93
+ <Button
94
+ Width="350"
95
+ Height="160"
96
+ Margin="5"
97
+ Background="#efebe9"
98
+ Command="{Binding DataContext.ClickMenu, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}"
99
+ CommandParameter="{Binding}">
100
+ <Button.Template>
101
+ <ControlTemplate TargetType="{x:Type Button}">
102
+ <Border
103
+ Name="border"
104
+ Background="{TemplateBinding Background}"
105
+ CornerRadius="10">
106
+ <ContentPresenter />
107
+ </Border>
108
+ <ControlTemplate.Triggers>
109
+ <Trigger Property="IsMouseOver" Value="True">
110
+ <Setter TargetName="border" Property="Background" Value="#FFBEE6FD" />
111
+ </Trigger>
112
+ </ControlTemplate.Triggers>
113
+ </ControlTemplate>
114
+ </Button.Template>
115
+ <DockPanel Margin="10">
116
+ <StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
117
+ <TextBlock
118
+ Margin="10,0,10,0"
119
+ HorizontalAlignment="Center"
120
+ VerticalAlignment="Center"
121
+ FontFamily="Segoe MDL2 Assets"
122
+ FontSize="18pt"
123
+ Text="{Binding Icon}" />
124
+ <TextBlock FontSize="18pt" Text="{Binding Title}" />
125
+ </StackPanel>
126
+ <TextBlock
127
+ FontSize="11pt"
128
+ Text="{Binding Description}"
129
+ TextWrapping="Wrap" />
130
+ </DockPanel>
131
+ </Button>
132
+ </DataTemplate>
133
+ </ItemsControl.ItemTemplate>
134
+ <ItemsControl.ItemsPanel>
135
+ <ItemsPanelTemplate>
136
+ <WrapPanel HorizontalAlignment="Center" />
137
+ </ItemsPanelTemplate>
138
+ </ItemsControl.ItemsPanel>
139
+ </ItemsControl>
140
+ </DataTemplate>
141
+
142
+ <local:HomeContentTemplateSelector x:Key="HomeContentTemplateSelector" Template="{StaticResource HomeContentTemplate}" />
143
+
144
+ <DataTemplate x:Key="MenuModelContentTemplate" DataType="{x:Type local:MenuModel}">
145
+ <ScrollViewer>
146
+ <StackPanel>
147
+ <TextBlock
148
+ Margin="15"
149
+ FontSize="23pt"
150
+ Foreground="Gray"
151
+ Text="{Binding Title}" />
152
+ <ContentPresenter
153
+ Margin="15"
154
+ Content="{Binding Content}"
155
+ ContentTemplateSelector="{StaticResource HomeContentTemplateSelector}" />
156
+ </StackPanel>
157
+ </ScrollViewer>
158
+ </DataTemplate>
159
+ </Window.Resources>
160
+
161
+ <Grid>
162
+ <TabControl
163
+ ContentTemplate="{StaticResource MenuModelContentTemplate}"
164
+ ItemContainerStyle="{StaticResource TabItemSidebarButtonStyle}"
165
+ ItemTemplate="{StaticResource SidebarButtonTemplate}"
166
+ ItemsSource="{Binding MenuModels}"
167
+ Style="{StaticResource TabControlSidebarStyle}"
168
+ TabStripPlacement="Left" />
169
+
170
+ <Button
171
+ Margin="15"
172
+ HorizontalAlignment="Right"
173
+ VerticalAlignment="Top"
174
+ Command="{Binding AddCommand}"
175
+ Content="Add" />
176
+ </Grid>
177
+ </Window>
178
+ ```
179
+
180
+ ```cs
181
+ using Prism.Commands;
182
+ using Prism.Mvvm;
183
+ using System.Collections.ObjectModel;
184
+ using System.Windows;
185
+ using System.Windows.Controls;
186
+ using System.Windows.Data;
187
+
188
+ namespace Questions329889_2
189
+ {
190
+ public class HomeContentTemplateSelector : DataTemplateSelector
191
+ {
192
+ public override DataTemplate SelectTemplate(object item, DependencyObject container)
193
+ => item is CollectionView ? Template : null;
194
+ public DataTemplate Template { get; set; }
195
+ }
196
+
197
+ public class MenuModel : BindableBase
198
+ {
199
+ public string Icon { get; init; }
200
+ public string Title { get; init; }
201
+ public string Description { get; init; }
202
+ public object Content { get; set; }
203
+
204
+ public bool IsSelected { get => _IsSelected; set => SetProperty(ref _IsSelected, value); }
205
+ private bool _IsSelected;
206
+ }
207
+
208
+ public class MainViewModel : BindableBase
209
+ {
210
+ public ObservableCollection<MenuModel> MenuModels { get; }
211
+ public DelegateCommand<MenuModel> ClickMenu { get; }
212
+ public DelegateCommand AddCommand { get; }
213
+
214
+ public MainViewModel()
215
+ {
216
+ MenuModels = new()
217
+ {
218
+ new()
219
+ {
220
+ IsSelected = true,
221
+ Icon = "\xE10F",
222
+ Title = "HOME",
223
+ },
224
+ new()
225
+ {
226
+ Icon = "\xF157",
227
+ Title = "CONTENT1",
228
+ Description = "CONTENT1 です。ここには、CONTENT1 の説明が入ります。",
229
+ Content = "CONTENT1 です。",
230
+ },
231
+ new()
232
+ {
233
+ Icon = "\xF158",
234
+ Title = "CONTENT2",
235
+ Description = "CONTENT2 です。ここには、CONTENT2 の説明が入ります。",
236
+ },
237
+ new()
238
+ {
239
+ Icon = "\xF159",
240
+ Title = "CONTENT3",
241
+ Description = "CONTENT3 です。ここには、CONTENT3 の説明が入ります。",
242
+ },
243
+ };
244
+
245
+ MenuModels[0].Content = new ListCollectionView(MenuModels)
246
+ {
247
+ Filter = (x) => ((MenuModel)x).Title != "HOME",
248
+ };
249
+
250
+ ClickMenu = new(x =>
251
+ {
252
+ foreach (var m in MenuModels)
253
+ m.IsSelected = x == m;
254
+ });
255
+
256
+ AddCommand = new(() =>
257
+ {
258
+ MenuModels.Add(new()
259
+ {
260
+ Icon = "\xF159",
261
+ Title = $"CONTENT{number}",
262
+ Description = $"CONTENT{number} です。ここには、CONTENT{number} の説明が入ります。",
263
+ });
264
+ number++;
265
+ });
266
+ }
267
+ private int number = 4;
268
+ }
269
+
270
+ public partial class MainWindow : Window
271
+ {
272
+ public MainWindow() => InitializeComponent();
273
+ }
274
+ }
275
+ ```
276
+ ![アプリ画像](https://ddjkaamml8q8x.cloudfront.net/questions/2023-07-27/a72b596e-600f-4e74-bc9a-35db8125ca58.png)