Прикрутить неуродливую группировку к DataGrid
20.11.2017, 19:14. Показов 497. Ответов 0
Доброго времени суток. Не уверен насчёт раздела форума, с дотнетом знаком неблизко
Есть 2 класса:
C# | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| /// <summary>
/// Пользователь
/// </summary>
internal class User
{
public long Id { get; set; }
public string Name { get; set; }
public IList<Luggage> Luggages { get; set; }
}
/// <summary>
/// Багаж
/// </summary>
internal class Luggage
{
public long Id { get; set; }
public string Name { get; set; }
public long WeightInKilogram { get; set; }
} |
|
Есть DataGrid для вывода, таблица с табличными данными.
Выводится Id/Name пользователя и 2 кнопки Удалить/Редактировать с указанием Id записи в Tag (Рисунок 1).
Весь код (MainWindow.xaml и MainWindow.xaml.cs):
Кликните здесь для просмотра всего текста
XML | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
| <Window x:Class="GroopingDemo.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"
mc:Ignorable="d"
Title="Grooping Datagrid Demo App"
Height="{Binding SystemParameters.PrimaryScreenHeight}"
Width="{Binding SystemParameters.PrimaryScreenWidth}"
MinWidth="525"
MinHeight="350"
WindowStartupLocation="CenterScreen"
d:DesignWidth="525"
d:DesignHeight="350"
Background="#d6dbe9">
<Grid>
<DataGrid Name="LuggageDataGrid"
AutoGenerateColumns="False"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
SelectionUnit="FullRow"
IsReadOnly="True">
<DataGrid.Columns>
<!-- Кнопка удаления -->
<DataGridTemplateColumn Width="25">
<DataGridTemplateColumn.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
</Style>
</DataGridTemplateColumn.CellStyle>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Name="DeleteButton"
Click="DeleteButton_OnClick"
Tag="{Binding Path=Id}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Cursor="Hand"
ToolTip="Удалить запись">
[D]
</Button>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<!-- Кнопка редактирования -->
<DataGridTemplateColumn Width="25">
<DataGridTemplateColumn.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
</Style>
</DataGridTemplateColumn.CellStyle>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Name="EditButton"
Click="EditButton_Click"
Tag="{Binding Path=Id}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Cursor="Hand"
ToolTip="Редактировать запись">
[E]
</Button>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<!-- Столбец ID -->
<DataGridTextColumn Header="Id"
IsReadOnly="True"
Width="1*"
Binding="{Binding Path=Id}">
<DataGridTextColumn.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
<!-- Столбец Name -->
<DataGridTextColumn Header="Имя"
IsReadOnly="True"
Width="4*"
Binding="{Binding Path=Name}">
<DataGridTextColumn.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="ToolTip" Value="{Binding Name}" />
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window> |
|
Кликните здесь для просмотра всего текста
C# | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
| using System.Collections.Generic;
using System.Windows;
namespace GroopingDemo
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
LuggageDataGrid.ItemsSource = Storage.GetUsers();
}
/// <summary>
/// Редактирование
/// </summary>
private void EditButton_Click(object sender, RoutedEventArgs routedEventArgs)
{
// TODO write later
MessageBox.Show(this, "Not implemented", "Message",
MessageBoxButton.OK, MessageBoxImage.Asterisk);
}
/// <summary>
/// Удаление
/// </summary>
private void DeleteButton_OnClick(object sender, RoutedEventArgs e)
{
// TODO write later
MessageBox.Show(this, "Not implemented", "Message",
MessageBoxButton.OK, MessageBoxImage.Asterisk);
}
/// <summary>
/// Имитация хранилища данных
/// </summary>
internal class Storage
{
private static readonly IList<User> Users = new List<User>();
static Storage() {
var userJohn = new User {
Id = 0,
Name = "John",
Luggages = new List<Luggage> {
new Luggage {Id = 0, Name = "Umbrella (Green)", WeightInKilogram = 1},
new Luggage {Id = 1, Name = "Bag (Adidas)", WeightInKilogram = 2},
new Luggage {Id = 2, Name = "Watermelon", WeightInKilogram = 5}
}
};
var userSarah = new User {
Id = 1,
Name = "Sarah",
Luggages = new List<Luggage> {
new Luggage {Id = 3, Name = "Umbrella (White)", WeightInKilogram = 2},
new Luggage {Id = 4, Name = "Feminine pads (Adidas)", WeightInKilogram = 1},
new Luggage {Id = 5, Name = "Water bottle", WeightInKilogram = 2}
}
};
var userHelen = new User {
Id = 2,
Name = "Helen",
Luggages = new List<Luggage> {
new Luggage {Id = 6, Name = "Notebook (Dell)", WeightInKilogram = 2}
}
};
Users.Add(userJohn);
Users.Add(userSarah);
Users.Add(userHelen);
}
internal static IEnumerable<User> GetUsers() {
return Users;
}
internal static bool DeleteById(long deletedId) {
var result = false;
for (var i = Users.Count - 1; i >= 0; i--) {
if (deletedId != Users[i].Id) {
continue;
}
Users.RemoveAt(i);
result = true;
}
return result;
}
}
}
/// <summary>
/// Пользователь
/// </summary>
internal class User
{
public long Id { get; set; }
public string Name { get; set; }
public IList<Luggage> Luggages { get; set; }
}
/// <summary>
/// Багаж
/// </summary>
internal class Luggage
{
public long Id { get; set; }
public string Name { get; set; }
public long WeightInKilogram { get; set; }
}
} |
|
Хочу прикрутить группировку записей о багаже к каждой записи пользователя, желательно с кнопками Редактировать/Удалить для каждой. Гуглил решения - часть не подошли из-за другой структуры классов, часть не запустилось.
Нашёл вот такое решение, заработало. Но оно ломает имеющееся форматирование (Рисунок 2).
Кликните здесь для просмотра всего текста
XML | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
| <Window x:Class="GroopingDemo.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"
mc:Ignorable="d"
Title="Grooping Datagrid Demo App"
Height="{Binding SystemParameters.PrimaryScreenHeight}"
Width="{Binding SystemParameters.PrimaryScreenWidth}"
MinWidth="525"
MinHeight="350"
WindowStartupLocation="CenterScreen"
d:DesignWidth="525"
d:DesignHeight="350"
Background="#d6dbe9">
<Grid>
<DataGrid Name="LuggageDataGrid"
AutoGenerateColumns="False"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
SelectionUnit="FullRow"
IsReadOnly="True">
<!-- Группировка -->
<DataGrid.GroupStyle>
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Expander IsExpanded="True">
<Expander.Header>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=Name}" />
</StackPanel>
</Expander.Header>
<Expander.Content>
<ItemsControl ItemsSource="{Binding Path=Items[0].Luggages}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=Id}"/>
<TextBlock Text="{Binding Path=Name}"/>
<TextBlock Text="{Binding Path=WeightInKilogram}"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Expander.Content>
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</DataGrid.GroupStyle>
<DataGrid.Columns>
<!-- Кнопка удаления -->
<DataGridTemplateColumn Width="25">
<DataGridTemplateColumn.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
</Style>
</DataGridTemplateColumn.CellStyle>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Name="DeleteButton"
Click="DeleteButton_OnClick"
Tag="{Binding Path=Id}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Cursor="Hand"
ToolTip="Удалить запись">
[D]
</Button>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<!-- Кнопка редактирования -->
<DataGridTemplateColumn Width="25">
<DataGridTemplateColumn.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
</Style>
</DataGridTemplateColumn.CellStyle>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Name="EditButton"
Click="EditButton_Click"
Tag="{Binding Path=Id}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Cursor="Hand"
ToolTip="Редактировать запись">
[E]
</Button>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<!-- Столбец ID -->
<DataGridTextColumn Header="Id"
IsReadOnly="True"
Width="1*"
Binding="{Binding Path=Id}">
<DataGridTextColumn.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
<!-- Столбец Name -->
<DataGridTextColumn Header="Имя"
IsReadOnly="True"
Width="4*"
Binding="{Binding Path=Name}">
<DataGridTextColumn.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="ToolTip" Value="{Binding Name}" />
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window> |
|
Кликните здесь для просмотра всего текста
C# | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
| using System.Collections.Generic;
using System.Windows;
using System.Windows.Data;
namespace GroopingDemo
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
LuggageDataGrid.ItemsSource = Storage.GetUsers();
// Указание поля группировки
var collectionView = CollectionViewSource.GetDefaultView(LuggageDataGrid.ItemsSource);
if (collectionView == null || !collectionView.CanGroup)
{
return;
}
collectionView.GroupDescriptions.Clear();
var propertyGroupDescription = new PropertyGroupDescription
{
PropertyName = "Name"
};
collectionView.GroupDescriptions.Add(propertyGroupDescription);
}
/// <summary>
/// Редактирование
/// </summary>
private void EditButton_Click(object sender, RoutedEventArgs routedEventArgs)
{
// TODO write later
MessageBox.Show(this, "Not implemented", "Message",
MessageBoxButton.OK, MessageBoxImage.Asterisk);
}
/// <summary>
/// Удаление
/// </summary>
private void DeleteButton_OnClick(object sender, RoutedEventArgs e)
{
// TODO write later
MessageBox.Show(this, "Not implemented", "Message",
MessageBoxButton.OK, MessageBoxImage.Asterisk);
}
/// <summary>
/// Имитация хранилища данных
/// </summary>
internal class Storage
{
private static readonly IList<User> Users = new List<User>();
static Storage() {
var userJohn = new User {
Id = 0,
Name = "John",
Luggages = new List<Luggage> {
new Luggage {Id = 0, Name = "Umbrella (Green)", WeightInKilogram = 1},
new Luggage {Id = 1, Name = "Bag (Adidas)", WeightInKilogram = 2},
new Luggage {Id = 2, Name = "Watermelon", WeightInKilogram = 5}
}
};
var userSarah = new User {
Id = 1,
Name = "Sarah",
Luggages = new List<Luggage> {
new Luggage {Id = 3, Name = "Umbrella (White)", WeightInKilogram = 2},
new Luggage {Id = 4, Name = "Feminine pads (Adidas)", WeightInKilogram = 1},
new Luggage {Id = 5, Name = "Water bottle", WeightInKilogram = 2}
}
};
var userHelen = new User {
Id = 2,
Name = "Helen",
Luggages = new List<Luggage> {
new Luggage {Id = 6, Name = "Notebook (Dell)", WeightInKilogram = 2}
}
};
Users.Add(userJohn);
Users.Add(userSarah);
Users.Add(userHelen);
}
internal static IEnumerable<User> GetUsers() {
return Users;
}
internal static bool DeleteById(long deletedId) {
var result = false;
for (var i = Users.Count - 1; i >= 0; i--) {
if (deletedId != Users[i].Id) {
continue;
}
Users.RemoveAt(i);
result = true;
}
return result;
}
}
}
/// <summary>
/// Пользователь
/// </summary>
internal class User
{
public long Id { get; set; }
public string Name { get; set; }
public IList<Luggage> Luggages { get; set; }
}
/// <summary>
/// Багаж
/// </summary>
internal class Luggage
{
public long Id { get; set; }
public string Name { get; set; }
public long WeightInKilogram { get; set; }
}
} |
|
Хотелось бы указывать в заголовке групировки Id и Name пользователя, в идеале чтобы групировка выглядела вот так (Рисунок 3). Или хотя бы так (Рисунок 4).
Буду благодарен, если укажете хороший материал по группировке, который подходит под эту ООП-иерархию. Или укажете на ошибку в суждениях.
0
|