Форум программистов, компьютерный форум, киберфорум
C#: WPF, UWP и Silverlight
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.94/47: Рейтинг темы: голосов - 47, средняя оценка - 4.94
3 / 4 / 0
Регистрация: 19.09.2016
Сообщений: 91

Как создать иерархическое меню

12.12.2019, 18:03. Показов 9918. Ответов 67
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Уважаемые, гуру, застрял на создании иерархическом меню, помогите, а то голову сломал. Наверняка есть уже решение этого вопроса, чтобы не изобретать велосипед, подскажите способы создания иерархического меню.
Задача в следующем. Есть класс с товарами и есть класс с категориями товаров.


C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Product
    {
        public int ProductId { get; set; }    
        public string ProductName { get; set; } // наименование
        public string Art { get; set; } // Артикул
 
        public int? CategoryId { get; set; }             // Категория
        public virtual Category Category { get; set; } /// Связь между классом  Product и Category один ко многим 
    }
 
public class Category
    {
        public int Id { get; set; }
        public int ParentId { get; set; }        //ID родительская категория
        public string CategoryTitle { get; set; }  //Наименование категории 
 
        public virtual ICollection<Product> Products { get; set; } ///  Связь между классом  Category и Product один ко многим                                                                   
      
        public Category()
        {
            Products = new List<Product>();
        }
    }

Данные храним в БД. Работа с БД осуществляется через EF через класс ModelContext.
Структура кода xaml в принципе проста. Имеется меню, и два рабочих поля, в левом разместил TreeView в котором и нужно получить иерархическое меню категорий товара. А а правом окне нужно выводить товары принадлежащие выделенному пункту категории иерархического меню.


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="WPF_Wood.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"
        xmlns:local="clr-namespace:WPF_Wood"
        xmlns:VM="clr-namespace:WPF_Wood"
        xmlns:viewModel="clr-namespace:WPF_Wood.ViewModel"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
 
 
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
        </Grid.RowDefinitions>
 
        <StackPanel Grid.ColumnSpan="2">
            <Menu>
                <MenuItem Header="Меню">
                    <MenuItem Header="Добавить категорию"></MenuItem>
                    <MenuItem Header="Изменить категорию"></MenuItem>
                    <MenuItem Header="Удалить категорию"></MenuItem>
                    <Separator />
                    <MenuItem Header="Добавить товар" Command="{Binding AddProductCommand}"></MenuItem>
                   
                    <MenuItem Header="Изменить товар" Command="{Binding EditProductCommand}"
                              CommandParameter="{Binding ElementName=prod_List, Path=SelectedItem}"
                              ></MenuItem>
 
                    <MenuItem Header="Удалить товар" 
                              Command="{Binding DeleteProductCommand}"
                          CommandParameter="{Binding ElementName=prod_List, Path=SelectedItem}">
                        
                    </MenuItem>
                </MenuItem>
            </Menu>
        </StackPanel>
 
        <StackPanel Grid.Row="1">
            <TreeView x:Name="MainTreeView" 
                      HorizontalAlignment="Stretch" Margin="10" 
                      VerticalAlignment="Stretch"
                      ItemsSource="{Binding CategoryParents}">
 
                <TreeView.ItemTemplate>
 
                    <!--Тут биндим категории товаров у которых ParentId => 0 -->
                    <HierarchicalDataTemplate ItemsSource="{Binding Positions}" 
                                              DataType="{x:Type viewModel:CategoryParent}" >
 
                        <Label Content="{Binding CategoryParentName}"/>
 
                        <HierarchicalDataTemplate.ItemTemplate>
                            <!--Тут биндим категории товаров у которых ParentId  -->
                            <HierarchicalDataTemplate ItemsSource="{Binding CategoryVM}" >
 
                                <Label Content="{Binding CategoryTitle}"/>
 
                                <!--Тут биндим категории товаров у которых ParentId  -->
                                <HierarchicalDataTemplate.ItemTemplate>
                                    <DataTemplate >
                                        <Label Content="{Binding EmployeeName}"/>
                                    </DataTemplate>
 
                                </HierarchicalDataTemplate.ItemTemplate>
 
                            </HierarchicalDataTemplate>
                        </HierarchicalDataTemplate.ItemTemplate>
                    </HierarchicalDataTemplate>
                </TreeView.ItemTemplate>
            </TreeView>
 
        </StackPanel>
 
        <ScrollViewer Grid.Row="1" Grid.Column="1" Margin="10" VerticalScrollBarVisibility="Auto">
 
            <ListView x:Name="prod_List" ItemsSource="{Binding ProductVM}" >
                <ListView.View>
                    <GridView>
                        <GridViewColumn DisplayMemberBinding="{Binding Path=ProductId}" Width="80">Id Товара</GridViewColumn>
                        <GridViewColumn DisplayMemberBinding="{Binding Path=ProductName}" Width="100">Наименование товара</GridViewColumn>
                        <GridViewColumn DisplayMemberBinding="{Binding Path= Art}" Width="80">Артикул</GridViewColumn>
                        <GridViewColumn DisplayMemberBinding="{Binding Path= CategoryName}" Width="80">Категория</GridViewColumn>
                    </GridView>
                </ListView.View>
               
            </ListView>
 
        </ScrollViewer>
 
        <StackPanel Grid.Row="2" Grid.ColumnSpan="2" Height="30">
            <ToolBarPanel />
        </StackPanel>
 
    </Grid>
</Window>

Я понимаю что нужно составить иерархическое дерево, для привязки его к TreeView, но как это сделать не могу врубиться. Примеров много пересмотрел, а вот идеи как лучше сделать не нашел.
Вложения
Тип файла: rar 00001 WPF_Wood_02.rar (12.94 Мб, 2 просмотров)
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
12.12.2019, 18:03
Ответы с готовыми решениями:

Не получается создать иерархическое меню
Здравствуйте. Пытаюсь создать иерархическое меню. Наткнулся на такую статью: ...

Иерархическое меню из четырёх кнопок. Как продумать логику реализации
Есть иерархическое меню из четырёх кнопок, одна кнопка активирует ещё две, т.е. всего шесть. Нажатие каждой из них записывает в...

Иерархическое меню
Здравствуйте! Необходимо сделать две менюшки, а то я немного задолбался. Знаю как вівести вертикальное, но не могу присобачить...

67
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,176
Записей в блоге: 2
20.12.2019, 10:51
Студворк — интернет-сервис помощи студентам
AII, да.
Свойство состоит всего из коллекции с одним объектом CategoryVM.
Как из экземпляра CategoryDTO получить экземпляр CategoryVM со всем деревом нижестоящих элементов , мы уже писали код выше.
TreeView привязываете к этой коллекции и задаёте ОДИН шаблон для развёртки. Он будет наследоваться нижестоящими уровнями.

Добавлено через 3 минуты
AII, и методы слегка избыточны
C#
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
        private HashSet<CategoryDTO> GetCategoryDtoHashSet() // Получаем категории 
        {
        //    var items = new List<Category>();
            var itemsDTO = new HashSet<CategoryDTO>();
 
            using (ModelContext db = new ModelContext())
            {
             //   items = db.Categorys.ToList();
                foreach (var it in db.Categorys)
                {
                    itemsDTO.Add(new CategoryDTO(it.Id, it.ParentId, it.CategoryTitle));
                }
            }
 
            return itemsDTO;
        }
Добавлено через 5 минут
AII, и в Модели очень редко имеет смысл использовать INPC.
В данном случае у вас в свойствах две коллекции Категории и Товары.
Но обе эти коллекции бессмысленно отслеживать на изменения.
Лучше вместо свойств сделать Методы и убрать INPC.
0
3 / 4 / 0
Регистрация: 19.09.2016
Сообщений: 91
20.12.2019, 14:22  [ТС]
Почему этот метод избыточен?
Цитата Сообщение от Элд Хасп Посмотреть сообщение
private HashSet<CategoryDTO> GetCategoryDtoHashSet()
Ведь я через него получаю значения из БД.

Добавлено через 1 минуту
Или можно по другому как то?

Добавлено через 5 минут
Цитата Сообщение от Элд Хасп Посмотреть сообщение
в Модели очень редко имеет смысл использовать INPC.
В данном случае у вас в свойствах две коллекции Категории и Товары.
Но обе эти коллекции бессмысленно отслеживать на изменения.
Лучше вместо свойств сделать Методы и убрать INPC.
Да, согласен. INPC поставил не подумав, смысла его точно нет. А методы, какие Вы имели ввиду?
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,176
Записей в блоге: 2
20.12.2019, 14:44
AII, я же показал.
Избыточен не сам метод, а инициализация им промежуточного списка.
Этот список только занимает место и не нужен.
Цикл сразу надо делать по возврату метода.

Внимательнее посмотрите мои правки в коде метода.

Добавлено через 1 минуту
AII, для более детального ответа покажите код класса ModelContext

Добавлено через 6 минут
Цитата Сообщение от All
Да, согласен. INPC поставил не подумав, смысла его точно нет. А методы, какие Вы имели ввиду?
Если есть необходимость получения всех линейных множеств Категорий или Товаров, то сделать для этого соответствующие методы.
Пока давайте "допилим" без них.
А потом при необходимости добавим.
Сейчас просто уберите свойства - закомментируйте их.
0
3 / 4 / 0
Регистрация: 19.09.2016
Сообщений: 91
20.12.2019, 14:44  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Внимательнее посмотрите мои правки в коде метода.
Да, все понял. Учту на будущее. Спасибо!

Мой ModelContext:
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
 public class ModelContext : DbContext
    {
        public ModelContext()
            : base("ProductContext")
        { }
 
 
        public DbSet<Product> Products { get; set; }
        public DbSet<Category> Categorys { get; set; }
 
 
        static ModelContext()
        {
            Database.SetInitializer<ModelContext>(new MyContextInitializer());
        }
 
       
        class MyContextInitializer : DropCreateDatabaseIfModelChanges<ModelContext>
        {
            protected override void Seed(ModelContext db)
            {
 
                //------------------------Инициализация бд  -------------------
 
                Category category = new Category
                {
                    ParentId = 0,
                    CategoryTitle = "Категория 0"
                };
 
                Category category1 = new Category
                {
                    ParentId = 1,
                    CategoryTitle = "Категория 1"
                };
                Category category2 = new Category
                {
                    ParentId = 0,
                    CategoryTitle = "Категория 2"
                };
                Category category3 = new Category
                {
                    ParentId = 0,
                    CategoryTitle = "Категория 3"
                };
                Category category4 = new Category
                {
                    ParentId = 3,
                    CategoryTitle = "Категория 4"
                };
                Category category5 = new Category
                {
                    ParentId = 1,
                    CategoryTitle = "Категория 5"
                };
 
                db.Categorys.AddRange(new List<Category> { category, category1, category2, category3, category4, category5 });
                db.SaveChanges();
                List<Product> prod = new List<Product>();
 
                for (int i = 1; i <= 5; i++)
                {
                    prod.Add(new Product()
                    {
                        ProductName = $"Товар {i}",
                        Art = $"ТОВАР № {i}",
                        CategoryId = 1
 
                    });
 
                    db.Products.AddRange(prod);
                    db.SaveChanges();
                }             
 
 
            }
           
        }
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,176
Записей в блоге: 2
20.12.2019, 14:49
AII, у вас оба свойства имеют тип DbSet и промежуточного списка для цикла по ним не нужно.
0
3 / 4 / 0
Регистрация: 19.09.2016
Сообщений: 91
21.12.2019, 15:30  [ТС]
Элд Хасп, добрый день!
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Сейчас просто уберите свойства - закомментируйте их.
Свойства убрал, отредактировал код методов. Что дальше нужно сделать?

Добавлено через 19 минут
Получилось:
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
public class Catalog 
    {
       public CategoryDTO GetCategory(HashSet<CategoryDTO> categories, HashSet<ProductDTO> products, int mainID)
        {
            // Получаем из множеств словари по ID
            Dictionary<int, CategoryDTO> dictCat = categories.ToDictionary(x => x.ID);
            Dictionary<int, ProductDTO> dictPrd = products.ToDictionary(x => x.ID);
 
            // Группируем по ID родительского каталога
            var groupCat = categories.ToLookup(x => x.ParentId);
            var groupPrd = products.ToLookup(x => x.CategoryId);
 
            // вызов рекурсивной локальной функции и возврат её значения
            return Create(mainID);
 
            // Локальная функция
            CategoryDTO Create(int id)
            {
                // Проверка наличия категории с заданным ID
                if (!dictCat.TryGetValue(id, out CategoryDTO category))
                      return null;
 
                // Создание массива из товаров этой категории
                var arrPrd = groupPrd[id];
 
                // Создание массива дочерних каталогов
                // Каждый каталог создаётся рекурсивным вызовом
                var arrCat = groupCat[id]?.Select(x => Create(x.ID));
 
                // Возврат нового значения с заполненными внутренними коллекциями
                return new CategoryDTO
                (
                    category.ID,
                    category.ParentId,
                    category.CategoryTitle,
                    arrPrd,
                    arrCat
                );
            }
        }
 
        public HashSet<CategoryDTO> GetCategoryDtoHashSet() // Получаем категории 
        {
            // var items = new List<Category>();
            var itemsDTO = new HashSet<CategoryDTO>();
 
            using (ModelContext db = new ModelContext())
            {
                //items = db.Categorys.ToList();
                foreach (var it in db.Categorys)
                {
                    itemsDTO.Add(new CategoryDTO(it.Id, it.ParentId, it.CategoryTitle));
                }
            }
 
            return itemsDTO;
        }
 
        public HashSet<ProductDTO> GetProductDtoHashSet() // Получаем товары 
        {
            var itemsDTO = new HashSet<ProductDTO>();
            //var items = new List<Product>();
 
            using (ModelContext db = new ModelContext())
            {
                //items = db.Products.ToList();
                foreach (var it in db.Products)
                {
                    itemsDTO.Add(new ProductDTO(it.ProductId, it.ProductName, it.Art, it.CategoryId));
                }
            }
            return itemsDTO;
        }
        
    }
Далее как я понимаю нужно из VM вытащить полученное дерево каталога.
Я создаю метод и в нем вызываю все значения:
C#
1
2
3
4
5
6
7
8
9
 public void GetCategoryVM()
        {
            Catalog Catalogs = new Catalog();
            HashSet<CategoryDTO> catDTO = Catalogs.GetCategoryDtoHashSet();
            HashSet<ProductDTO> prodDTO = Catalogs.GetProductDtoHashSet();
            CategoryDTO CategoriasDTO = Catalogs.GetCategory(catDTO, prodDTO, 1);
 
            
        }
Подскажите, куда лучше разворачивать все это дерево? Чтобы потом можно легко было с ним работать?
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,176
Записей в блоге: 2
21.12.2019, 18:52
AII, пару дней без меня...
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,176
Записей в блоге: 2
22.12.2019, 12:33
AII, примерный код извлечения дерева из Model
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Catalog 
    {
       public CategoryDTO GetCategoriesTree()
           => GetCategory(GetCategoryDtoHashSet() , GetProductDtoHashSet(), id главного каталога);
       public CategoryDTO GetCategory(HashSet<CategoryDTO> categories, HashSet<ProductDTO> products, int mainID)
        {
            ...
        }
 
        public HashSet<CategoryDTO> GetCategoryDtoHashSet() // Получаем категории 
        {
            ...
        }
 
        public HashSet<ProductDTO> GetProductDtoHashSet() // Получаем товары 
        {
            .....
        }
        
    }
C#
1
2
3
4
5
6
7
8
9
10
public class ViewModel
{
    private readonly Catalog catalog;
    public CategoryVM[] CategoriesTree {get;}
    public ViewModel ()
    {
         catalog = new Catalog ();
         CategoriesTree = new CategoryVM[] {new CategoryVM (catalog.GetCategoriesTree())};
    }
}
Добавлено через 1 минуту
К свойству CategoriesTree можно привязать TreeView.
0
3 / 4 / 0
Регистрация: 19.09.2016
Сообщений: 91
23.12.2019, 08:45  [ТС]
Привязался :
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
   <TreeView x:Name="MainTreeView" 
                      HorizontalAlignment="Stretch" Margin="10" 
                      VerticalAlignment="Stretch"
                      ItemsSource="{Binding CategoriesTree}">
 
                <TreeView.ItemTemplate>
 
                    <HierarchicalDataTemplate ItemsSource="{Binding CategoriesVM }" >
 
                        <TextBlock Text="{Binding CategoryTitle}"/>                     
                          
                                <HierarchicalDataTemplate.ItemTemplate>
                                    <DataTemplate >
                                        <TextBlock Text="{Binding CategoryTitle}"/>
                                    </DataTemplate>
 
                                </HierarchicalDataTemplate.ItemTemplate>
                    </HierarchicalDataTemplate>
                </TreeView.ItemTemplate>
            </TreeView>
К сожалению выводится только Одна ветка одного уровня.
Миниатюры
Как создать иерархическое меню  
0
3 / 4 / 0
Регистрация: 19.09.2016
Сообщений: 91
23.12.2019, 08:57  [ТС]
Убрал избыточный код:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 <TreeView x:Name="MainTreeView" 
                      HorizontalAlignment="Stretch" Margin="10" 
                      VerticalAlignment="Stretch"
                      ItemsSource="{Binding CategoriesTree}">
 
                <TreeView.ItemTemplate>
 
                    <HierarchicalDataTemplate ItemsSource="{Binding CategoriesVM }" >
 
                        <TextBlock Text="{Binding CategoryTitle}"/>                     
                          
                                <!--<HierarchicalDataTemplate.ItemTemplate>
                                    <DataTemplate >
                                        <TextBlock Text="{Binding CategoryTitle}"/>
                                    </DataTemplate>
 
                                </HierarchicalDataTemplate.ItemTemplate>-->
                          
                       
                    </HierarchicalDataTemplate>
                </TreeView.ItemTemplate>
            </TreeView>
Миниатюры
Как создать иерархическое меню   Как создать иерархическое меню  
0
3 / 4 / 0
Регистрация: 19.09.2016
Сообщений: 91
23.12.2019, 09:21  [ТС]
Отредактировал значения в БД, все шикарно работает:
Миниатюры
Как создать иерархическое меню  
0
3 / 4 / 0
Регистрация: 19.09.2016
Сообщений: 91
23.12.2019, 09:31  [ТС]
А как сделать что бы при выборе категории отображались товары только этой категории, через события?
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,176
Записей в блоге: 2
23.12.2019, 09:42
AII, у TreeView есть свойство только для чтения - SelectedItem.
Привязку VM к нему делаете через Behavior.
Мой вариант Behavior для привязки свойств только для чтения [WPF, Элд Хасп]
В свойстве VM вы получите выделенную категорию.
У категории есть свойство со списком её товаров.
0
3 / 4 / 0
Регистрация: 19.09.2016
Сообщений: 91
23.12.2019, 10:30  [ТС]
Behavior - Как я прочел, это класс в студии, как его подключить? Почему то студия его не видит.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,176
Записей в блоге: 2
23.12.2019, 11:23
AII, надо подключить System.Windows.Interactivity.dll.
Это Библиотека на GitHub сейчас.

Добавлено через 8 минут
AII, можно и без Behavior.
К TreeView подключаете обработчик на SelectedItemChanged.
В обработчике приводите выделенный элемент к нужному типу и присваиваете свойству ViewModel.
Допустим, тип ViewModel имеет такое же названием.
И в нем свойство CategoryVM SelectedCategory

Тогда в обработчике код
C#
1
((ViewModel)DataContext). SelectedCategory = treeView.SelectedItem as CategoryVM;
Добавлено через 1 минуту
Behavior делает тоже самое, только код инкапсулирован и может применяться в XAML к любым свойством без использования CB.
0
3 / 4 / 0
Регистрация: 19.09.2016
Сообщений: 91
24.12.2019, 07:30  [ТС]
Доброе утро, Элд Хасп!

В КБ я обрабатываю событие:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = new ApplicationViewModel();
        }
 
        private void SelectionChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
        {
            ((ApplicationViewModel)DataContext).selectCategoryVM = MainTreeView.SelectedItem as CategoryVM;
 
        }
    }
В VM - ApplicationViewModel создал свойство:
C#
1
  public CategoryVM selectCategoryVM { get; set; }
В XAML :

C#
1
2
3
4
5
6
7
8
9
10
11
<ListView x:Name="prod_List" ItemsSource="{Binding selectCategoryVM.Products}" >
                <ListView.View>
                    <GridView>
                        <GridViewColumn DisplayMemberBinding="{Binding Path=ID}" Width="80">Id Товара</GridViewColumn>
                        <GridViewColumn DisplayMemberBinding="{Binding Path=ProductName}" Width="100">Наименование товара</GridViewColumn>
                        <GridViewColumn DisplayMemberBinding="{Binding Path= Art}" Width="80">Артикул</GridViewColumn>
                        <GridViewColumn DisplayMemberBinding="{Binding Path= CategoryName}" Width="80">Категория</GridViewColumn>
                    </GridView>
                </ListView.View>
               
            </ListView>
Что я не так делаю?
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,176
Записей в блоге: 2
24.12.2019, 07:39
AII, архив проекта скиньте.
0
3 / 4 / 0
Регистрация: 19.09.2016
Сообщений: 91
24.12.2019, 07:43  [ТС]
Архив во вложении
Вложения
Тип файла: rar 00001 WPF_Wood_06.rar (12.98 Мб, 2 просмотров)
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,176
Записей в блоге: 2
25.12.2019, 16:54
Лучший ответ Сообщение было отмечено Элд Хасп как решение

Решение

AII, там у вас большая каша.
Раскидал по нескольким проектам, чтобы вы дальше не создавали путаницу.
Как с Базой работать - не разобрался.
Поставил коллекции-заглушки чтобы возвращали корректные значения.

TreeView - работает нормально.
Товары выбранной категории отображаются правильно.

По вопросу в этой теме - всё решено.
Если делать целиком задачу, то там многое что ещё надо делать.
И у проблем "ноги растут" из слоя Модель-База.

Если продолжать дальше, то надо сначала отладить работу с Базой. И лучше не в этой теме.
Создайте новую тему в которой для начала нужно будет создать полностью работающую Модель.

Архив решения приложен. Посмотрите. С чем не сможете разобраться - пишите.
Вложения
Тип файла: 7z 00001 WPF_Wood_06(1225).7z (9.28 Мб, 2 просмотров)
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,176
Записей в блоге: 2
26.12.2019, 01:31
AII, у вас неправильно инициализировалась База.
И по этим данным потом не могло построиться дерево категорий.

Поменяйте инициализацию на такую
C#
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
        class MyContextInitializer : DropCreateDatabaseIfModelChanges<ModelContext>
        {
            protected override void Seed(ModelContext db)
            {
 
                //------------------------Инициализация бд  -------------------
                List<Category> categories = new List<Category>()
                {
                    new Category{ParentId = 0, Id=1, CategoryTitle = "Категория 0"},
                    new Category{ParentId = 1, Id=2, CategoryTitle = "Категория 1"},
                    new Category{ParentId = 1, Id=3, CategoryTitle = "Категория 2"},
                    new Category{ParentId = 2, Id=4, CategoryTitle = "Категория 3"},
                    new Category{ParentId = 3, Id=5, CategoryTitle = "Категория 4"},
                    new Category{ParentId = 3, Id=6, CategoryTitle = "Категория 5"}
                };
 
                db.Categorys.AddRange(categories);
                //db.SaveChanges();
 
                Random random = new Random();
 
                List<Product> prod = new List<Product>();
 
                for (int i = 1; i <= 35; i++)
                {
                    prod.Add(new Product()
                    {
                        ProductName = $"Товар {i}",
                        Art = $"ТОВАР № {i}",
                        CategoryId = categories[random.Next(categories.Count)].Id
                    }
                    );
                }
 
                db.Products.AddRange(prod);
                db.SaveChanges();
 
            }
 
        }
И уберите заглушки из Модели - всё правильно работает.

Добавлено через 1 минуту
Да! Не забудьте после внесения изменений, перед запуском удалить созданную базу.
Иначе она не будет по новой инициализирована.

Добавлено через 8 минут
Пытался довести до ума редактирование/добавление/удаление сущностей в Базе, но в такой структуре приложения очень трудно что-либо изменить.

По сути если делать нормально, то надо пересоздать Модель.
В ней толком не работают обе части: взаимодействие с Базой и с ViewModel.

Работает только первичное чтение.
Можно добавить изменение/удаление/добавление в Базу.
Но отображаться в ViewModel эти изменения не будут.

То есть первый шаг - как создавать и отображать дерево вы, наверное, уже поняли.
А для нормальной связи с базой, нужно создавать другую структуру.
Не статическую как сейчас, а динамическую - узлу создаются по мере их раскрытия.
И выделенный узел поддерживается в актуальном состоянии.

Тогда уже с базой сможет работать одновременно несколько пользователей и база может быть обширной с изображением, видео и т.п.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
26.12.2019, 01:31

Иерархическое меню и госы
Доброе время суток всем! Прошу помощи у меня завтра госы, а я не могу найти пример создания иерархического меню. Помогите,...

Иерархическое меню работающее вне ОС
в общем дали задачу - &quot;со звездочкой&quot;, нужно написать программу менюшку, но условие такое - она должна работать вне ОС и использовать лишь...

Как сделать иерархическое представление данных?
Собственно, вот и весь вопрос. Есть таблица, с пиримеру - номенклатура. Как реализовать показ данных из этой таблицы иерархически? т.е....

Создать проект. Создать разделы меню. Вызвать форму из главного меню
Приветствую Всех. Недавно зарегистрировался на данном форуме. Вопрос и соответственно большая просьба. Пытаюсь создать проект, проявился...

Как создать контекстное меню. Например нажимая на richTextBox правой кнопкой мыши, мне бы предоставлялось контекстное меню
Как создать контекстное меню. Например нажимая на richTextBox правой кнопкой мыши, мне бы предоставлялось контекстное меню???


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
60
Ответ Создать тему
Новые блоги и статьи
Запустил конкурс "тем и промптов для текстовых квестов созданных почти чисто ИИ"
Adler 06.10.2026
Всем привет! За последние три-четыре дня я создал более 16 текстовых квестовых игр используя преимущественно по одному запросу к ИИ на игру. Мне так понравилось смотреть все ветки/ сцены во всех. . .
ИИ не может найти нужный язык в списке
Supersumestria 05.10.2026
Я ему даю вот такое изображение и прошу найти и подчеркнуть немецкий язык. Возвращает он вот это: https:/ / i. **********/ vqBWLe2. png Нужную строчку в 3й колонке просто выдумал. . Это. . .
Новая последняя моя музыка в SUNO
zorxor 05.10.2026
Здравствуйте, дорогие мои друзья! С большой радостью я хотел бы представить вам свою новую последнею музыку, которую сгенерировала мне по моей просьбе нейросеть SUNO. С уважением, zorxor. Это. . .
Программный домашний кинотеатр
russiannick 27.09.2026
Сподобился на программный домашний кинотеатр. В качестве ЯВУ по традиции выбрал js. В помощники взял Яндекс-Алису. Было создано три зала на разные интересы. исторические и ретро сериал Хичкок. . .
Беседа с ИИ о программистах, недопускающих к созданию и правке кода генеративные ИИ и причины этого
zorxor 21.09.2026
Раньше я радовался или получал некоторые эмоции, пусть небольшие, но всё же, от самого процесса написания кода, рекомпиляции и запуска, видя постепенное развитие программы и прочее. А теперь лень. . .
Мобильное приложение ColorStep
pavlinmavlin 17.09.2026
Реализовал приложение Красный, Зеленый, Синий в Unity3d + c#. Название изменил на ColorStep. Приложение прошло модерацию и теперь доступно для скачивания. Делал его сам, шаг за шагом — и вот,. . .
Запрет дублирования строк в табличной части
Maks 13.09.2026
Реализация из решения ниже выполнена на нетиповом справочнике "Нормы ТО" с табличной часть "Виды ТО", разработанного в КА2, со следующими реквизитами: - ВидТО (СправочникСсылка. ВидыТО); - ВидГСМ. . .
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Jin X 06.09.2026
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр. Работая с форумом и нейросетями в браузере часто хочется что-то подкорректировать или добавить какого-то функционала. Ниже прикреплён. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru