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

Работа с ListBox WPF

08.02.2024, 21:17. Показов 2015. Ответов 29
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Доброго времени суток!

У меня есть форма на которой Grid имеет две колонки. В одной ListBox, в другой TextBlock. У меня есть список List<Ontology>. Мне необходимо добавить в ListBox мой List<Ontology> и в нем отображать свойство Name, а в TextBlock свойство Description элемента ListBox на котором фокус, а так же при двойном нажатии на элемента ListBox открывать в ListBox List<Definition> и отображать его свойство Name, а в TextBlock свойство Description класса Definition. И при обратном двойном клике возвращаться к представлению List<Ontology>.

C#
1
2
3
4
5
6
7
8
9
10
11
12
 public class Ontology :  IEntity
 {
     public string Name { get; set; }
     public string Description { get; set; }
     public List<Definition> Definitions { get; set; } = new();
 
     public Ontology( string name, string description)
     {
         Name = name;
         Description = description;
     }
 }
C#
1
2
3
4
5
6
7
8
9
10
11
12
public class Definition : IEntity
 {
     public string Name { get; set; }
 
     public string Description { get; set; }
 
     public Definition(string name, string description)
     {
         Name = name;
         Description = description;
     }
 }
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
08.02.2024, 21:17
Ответы с готовыми решениями:

C# WPF Прокрутка ListBox'a
Ситуация такая. В ListBox'e есть элементы, не важно какие. При зажатии кнопки мыши на одном из них и дальнейшем перетаскивании курсора мыши...

WPF Binding ListBox
Есть tabControl с 2 вкладками в обоих заложен ListBox ( и у каждого из них заложен TextBlock c CheckBox): создал привязку к 1 listbox все...

ListBox сохранение WPF
Я сделал что то на подобии чата из listbox, textbox и button Хочу чтоб все что я написал в listbox сохранялся в файлик. И при следующем...

29
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16151 / 11272 / 2890
Регистрация: 21.04.2018
Сообщений: 33,146
Записей в блоге: 2
09.02.2024, 22:18
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от xellan24rus Посмотреть сообщение
ObservableCollection реализует интерфейс INotifyPropertyChanged
НЕТ!

Реализует интерфейс INotifyCollectionChanged.

Цитата Сообщение от xellan24rus Посмотреть сообщение
А другие коллекции, к примеру как List, не реализуют интерфейс INotifyPropertyChanged
Несколько сложнее.
Не для это темы. На заметку: BindigList и DataView тоже обеспечивают уведомление об изменениях.

Цитата Сообщение от Diagn0z Посмотреть сообщение
общая концепция паттерна MVVM мне ясна
Это один из паттернов семейства MV*.
Вам понятна концепция этого семейства?
1
 Аватар для xellan24rus
364 / 296 / 55
Регистрация: 08.04.2020
Сообщений: 1,175
09.02.2024, 22:22
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Реализует интерфейс INotifyCollectionChanged.
Да верно, хорошо что подметили.
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Несколько сложнее.
Не для это темы. На заметку: BindigList и DataView тоже обеспечивают уведомление об изменениях.
Но как вы и написали не для этой темы, человек только учит азы, не будем же его грузить информацией которая ему пригодится точно не скоро.
0
3 / 3 / 0
Регистрация: 10.02.2023
Сообщений: 91
09.02.2024, 22:59  [ТС]
Отличная идея, я так и думал

Добавлено через 1 минуту
Цитата Сообщение от xellan24rus Посмотреть сообщение
Как вам такой вариант при двойном клике открывается окошко для редактирования? А по кнопке добавить, аналогично
Отличная идея, я об этом задумался

Добавлено через 33 секунды
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Вам понятна концепция этого семейства?
Если только в общих чертах, как до этого отмечали уже в этой статье, но на практике реализовать не доводилось
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16151 / 11272 / 2890
Регистрация: 21.04.2018
Сообщений: 33,146
Записей в блоге: 2
09.02.2024, 23:11
Цитата Сообщение от Diagn0z Посмотреть сообщение
но на практике реализовать не доводилось
Чтобы "прочувствовать" создайте решение из четырёх проектов:
1) Модель - библиотека классов Standard 2. Не имеет ссылки на другие проекты;
2) ViewModel - библиотека классов Standard 2. Имеет ссылку на проект Модель;
3) View - библиотека классов для WPF. Ссылка на проект ViewModel;
4) App - приложение. Имеет ссылку на все другие проекты Решения.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16151 / 11272 / 2890
Регистрация: 21.04.2018
Сообщений: 33,146
Записей в блоге: 2
10.02.2024, 10:55
Цитата Сообщение от xellan24rus Посмотреть сообщение
DataContext это прослойка которая работает рука об руку с привязкой данных, предоставляя деревьям элементов доступ к определенному набору данных.
Это свойство FrameworkElement, которое используется по умолчанию в качестве объекта-источника в привязках этого FrameworkElement.
Объект-источник в привязке может быть явно задан в одном из свойств: Source, RelativeSource и ElementName. Если нет явного задания, вот тогда используется объект источник из свойства DataContext.

При этом надо понимать, что объект-источник в DataContext это необязательно ViewModel. Например, очень часто используется привязка в иерархическом представлении не к текущему контексту данных, а к VM на другом уровне иерархии. Особенно часто это используют для команд кнопок, во всплывающих окнах (Popup, ContextMenu и др.).
1
 Аватар для xellan24rus
364 / 296 / 55
Регистрация: 08.04.2020
Сообщений: 1,175
10.02.2024, 21:18
Лучший ответ Сообщение было отмечено Diagn0z как решение

Решение

Diagn0z,
Пример
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
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Threading.Tasks;
 
namespace Diagn0z_Exemple_JsonToView
{
    public class MainViewModel : Viewbase
    {
        public ObservableCollection<Data> DataCollection { get; set; }
        public MainViewModel()
        {
            DataCollection = JsonSerializer.Deserialize<ObservableCollection<Data>>(File.ReadAllText("Data.json"));
        }
    }
    public class Data : Viewbase
    {
        private string _Name { get; set; }
 
        public string Name
        {
            get => _Name;
            set
            {
                _Name = value;
                OnPropertyChanged(nameof(Name));
            }
        }
        private string _Description { get; set; }
 
        public string Description
        {
            get => _Description;
            set
            {
                _Description = value;
                OnPropertyChanged(nameof(Description));
            }
        }
        private Definition[] _Definitions { get; set; }
 
        public Definition[] Definitions
        {
            get => _Definitions;
            set
            {
                _Definitions = value;
                OnPropertyChanged(nameof(Definitions));
            }
        }
    }
 
    public class Definition : Viewbase
    {
        private string _Name { get; set; }
 
        public string Name
        {
            get => _Name;
            set
            {
                _Name = value;
                OnPropertyChanged(nameof(Name));
            }
        }
        private string _Description { get; set; }
 
        public string Description
        {
            get => _Description;
            set
            {
                _Description = value;
                OnPropertyChanged(nameof(Description));
            }
        }
    }
    public class Viewbase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
 
        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
Это класс с нашей моделью для view
В нем реализовал интерфейс INotifyPropertyChanged
C#
1
Viewbase : INotifyPropertyChanged
Для уведомления view об изменениях свойств.
Для
C#
1
public ObservableCollection<Data> DataCollection { get; set; }
Я не делал OnPropertyChanged как для других свойств так как ObservableCollection реализует интерфейс INotifyCollectionChanged, то есть добавление и удаление будут отображаться во view сразу.

C#
1
DataCollection = JsonSerializer.Deserialize<ObservableCollection<Data>>(File.ReadAllText("Data.json"));
В DataCollection я десилиризовал Json для примера.

Далее код MainWindow.cs
В нем я комметировал код.
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
using System.IO;
using System.Text;
using System.Text.Json;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
 
namespace Diagn0z_Exemple_JsonToView
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        MainViewModel ViewModel { get; set; }
        public MainWindow()
        {
            InitializeComponent();
            ViewModel = new MainViewModel();
            DataContext = ViewModel;
        }
 
        private void ListView_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            if (sender is ListBox listView)
            {
                // Получаем выделенный элемент
                if (listView.SelectedItem is Data selectedItem)
                {
                    // Находим ListViewChild внутри выбранного элемента
                    var listViewChild = FindVisualChild<ListBox>(listView.ItemContainerGenerator.ContainerFromItem(selectedItem) as DependencyObject, "ListViewChild");
                    if (listViewChild != null)
                    {
                        // Изменяем видимость ListViewChild
                        if (listViewChild.Visibility == Visibility.Visible)
                        {
                            listViewChild.Visibility = Visibility.Collapsed;
                        }
                        else
                        {
                            listViewChild.Visibility = Visibility.Visible;
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Метод для поиска элементов в визуаьльном дереве.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <param name="childName"></param>
        /// <returns></returns>
        private T FindVisualChild<T>(DependencyObject obj, string childName) where T : DependencyObject
        {
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
            {
                var child = VisualTreeHelper.GetChild(obj, i);
                if (child != null && child is T && (child as FrameworkElement).Name == childName)
                {
                    return (T)child;
                }
                else
                {
                    var childOfChild = FindVisualChild<T>(child, childName);
                    if (childOfChild != null)
                    {
                        return childOfChild;
                    }
                }
            }
            return null;
        }
 
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            if (listView.SelectedItems != null)
            {
                var SelectedItem = ((ListBoxItem)listView.ContainerFromElement((Button)sender)).Content; //Находим Item в котором находится кнопка
                if (SelectedItem == null)
                    return;
                ViewModel.DataCollection.Remove(SelectedItem as Data); //Удаляем из коллекции текущий Item, во View изменения сразу отобразятся.
            }
        }
    }
}
xaml

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
<Window x:Class="Diagn0z_Exemple_JsonToView.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:Diagn0z_Exemple_JsonToView"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="300"></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
        </Grid.ColumnDefinitions>
 
        <ListBox x:Name="listView" 
                  MouseDoubleClick="ListView_MouseDoubleClick"
                  ItemsSource="{Binding DataCollection}" 
                  SelectedItem="{Binding Description, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"  
                  HorizontalContentAlignment="Stretch">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Border Padding="1">
                        <StackPanel>
                            <Grid>
                                <Grid.RowDefinitions>
                                    <RowDefinition></RowDefinition>
                                    <RowDefinition></RowDefinition>
                                </Grid.RowDefinitions>
                             <TextBlock Text="{Binding Name}" FontWeight="Bold"/>
                            <TextBlock Grid.Row="1" Text="{Binding Description}" Margin="0 5 0 0"/>
                                <Button x:Name="btnDelete" Grid.RowSpan="2" VerticalAlignment="Center" HorizontalAlignment="Right" Width="15" Click="Button_Click">X</Button>
                            </Grid>
                            <ListBox x:Name="ListViewChild" 
                                     ItemsSource="{Binding Definitions}"
                                     HorizontalContentAlignment="Stretch"
                                     BorderThickness="0"
                                     Visibility="Collapsed">
                                <ListBox.ItemTemplate>
                                    <DataTemplate>
                                        <Border BorderBrush="Gray" BorderThickness="1" Padding="5">
                                            <StackPanel>
                                                <TextBlock Text="{Binding Name}"  Margin="0 5 0 0" FontWeight="Bold"/>
                                                <TextBlock Text="{Binding Description}" Margin="0 5 0 0"/>
                                            </StackPanel>
                                        </Border>
                                    </DataTemplate>
                                </ListBox.ItemTemplate>
                            </ListBox>
                        </StackPanel>
                    </Border>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
 
        <Grid Grid.Column="1">
            <Grid.RowDefinitions>
                <RowDefinition Height="50"></RowDefinition>
                <RowDefinition Height="auto"></RowDefinition>
                <RowDefinition Height="auto"></RowDefinition>
                <RowDefinition Height="auto"></RowDefinition>
                <RowDefinition Height="*"></RowDefinition>
            </Grid.RowDefinitions>
            <TextBox Margin="10 10 10 0" Text="{Binding SelectedItem.Description, ElementName=listView, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" BorderThickness="1" BorderBrush="#DDDDDD">
            </TextBox>
        </Grid>
    </Grid>
</Window>
В ItemTemplate мы можем настроить вид Item как угодно, ничто даже не помешает разместить там ещё один LisBox.
В главном Lisbox я указал привязку для свойства SelectedItem, в привязке указал UpdateSourceTrigger и Mode
XML
1
SelectedItem="{Binding Description, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Далее textbox
XML
1
  <TextBox Margin="10 10 10 0" Text="{Binding SelectedItem.Description, ElementName=listView, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" BorderThickness="1" BorderBrush="#DDDDDD">
Указываем привязку к SelectedItem указав по имени к какому элементу ElementName=listView, также указал Mode и Mode UpdateSourceTrigger. Теперь при выборе Item в Textbox отображается выбранный и при изменение текста textbox или в коде для SelectedItem, у SelectedItem меняется значение во view.
На Item добавил кнопку удаления из коллекции.
Чтобы при двойном клике открывалось окошко у дочернего ListBox можете скопировать код такого же события. И передать в новую форму объект Data, редактирование всех свойств точно такое же как с TextBox. Если что то не понятно будет пишите.

Конечно не лучший пример хорошей реализации, а решение для вопроса только. По хорошему счёту лучше Custom Control на основе ListboX создать. Но тут вопрос состоит насколько это вам надо. Если только в учебных целях, то лучше выбрать что то попроще.
Diagn0z_Exemple-JsonToView.rar
1
 Аватар для xellan24rus
364 / 296 / 55
Регистрация: 08.04.2020
Сообщений: 1,175
10.02.2024, 21:22
И если делать Custom Control для вашей задачи то лучше использовать TreeView Но у него придется переписать полностью шаблон, реализовать свойства SelectedItem. Select у него во всех случаях доступен. Но чтобы этим заняться, нужно больше опыта и практики с шаблонами.
1
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16151 / 11272 / 2890
Регистрация: 21.04.2018
Сообщений: 33,146
Записей в блоге: 2
10.02.2024, 22:18
Цитата Сообщение от xellan24rus Посмотреть сообщение
public ObservableCollection<Data> DataCollection { get; set; }
Лучше закрыть сеттер: DataCollection { get; /*set;*/ }
1
 Аватар для xellan24rus
364 / 296 / 55
Регистрация: 08.04.2020
Сообщений: 1,175
10.02.2024, 23:33
Элд Хасп, можно итак, я не знаю целей автора. Решит сам нужно это ему или нет. В целом я везде указал set и везде заготовки есть для правок через привязки или код, как пример с textbox одну сделал для примера что не обязательно в c# лезть чтобы изменения делать.
2
3 / 3 / 0
Регистрация: 10.02.2023
Сообщений: 91
13.02.2024, 19:59  [ТС]
Спасибо Вам большое, возьму это решения за образец
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
13.02.2024, 19:59
Помогаю со студенческими работами здесь

[WPF] ListBox не обновляется
Суть проблемы - ListBox внешне не обновляется при редактировании элемента... Код ListBox'a: &lt;ListBox...

ListBox иерархическое отображение (WPF)
Всем привет, у меня есть патерн Composite возможно както отобразить в виде иерархии даные в ListBox или treeview код програмы static...

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

WPF: Привязка коллекции к ListBox
Привет. Пытаюсь привязать коллекцию, но что-то не особо выходит. Окно выводится пустое public partial class MainWindow : Window ...

WPF Заполнение ListBox из БД aCCES
В C# делал просто так: listbox2.DataSource = cbs; listbox2.DisplayMember = &quot;cat_name&quot;; А как в WPF заполнить заполнить лист бокс...


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

Или воспользуйтесь поиском по форуму:
30
Ответ Создать тему
Новые блоги и статьи
Модель здравоСохранения 15. Как мы чинили AnyLogic модель рабочего коллектива: сочленение диаграммы состояний болезней и поломок в ресурспул
anaschu 23.05.2026
Как мы чинили AnyLogic модель рабочего коллектива Сегодня разобрались с пятью багами, из-за которых модель либо падала с ошибкой, либо давала совершенно бессмысленные результаты. Каждый баг был. . .
Диалоги с ИИ
zorxor 23.05.2026
Насколько я понимаю - Вы - Искусственный Интеллект. Это так? Да, всё верно. Я — искусственный интеллект. Я представляю собой большую языковую модель, созданную для помощи в самых разных задачах. . . .
Модель здравосохранения 14. Собираем всю модель вместе.
anaschu 22.05.2026
Модель собрана. В будущих постах на видео я покажу, как она работает. В этом посте запускаем её, проверяем результаты и разбираем что можно с ней делать дальше. Перед запуском проверяем. . .
Модель здравоохранения 13. Добавление самой системы здравоохранения.
anaschu 22.05.2026
В предыдущем посте мы настроили болезни. Теперь добавим события, которые управляют здоровьем всего коллектива, а также настроим рабочий график и расчёт финансов. В Main создаём четыре события. . . .
Модель здравоохранения 12. добавление болезней через ресурпул, как аварии
anaschu 22.05.2026
Болезни — это ключевая часть нашей модели. Нам нужно, чтобы работник периодически уходил на больничный, его задание при этом зависало, а после выздоровления работа возобновлялась. Реализуем это двумя. . .
Модель здравоохранения 11. Создаём классы Задание и Работник
anaschu 22.05.2026
В AnyLogic каждая заявка и каждый ресурс — это объект определённого класса. Нам нужно создать два класса: Задание (заявка) и Работник (ресурс). Класс Задание В дереве проекта нажимаем правой. . .
Модель здравоохранения 10. Новая модель, смотрим, как добавлять логические блоки, и что писать внутри
anaschu 22.05.2026
Открываем AnyLogic, создаём новый проект. В дереве проекта появляется класс Main — это главный агент, в котором будет жить вся наша логика. Палитра блоков Слева находится палитра. Нас интересует. . .
модель ЗдравоСохранения 9. Новая модель, разбираемся, как ее создавать
anaschu 22.05.2026
В этой серии постов мы построим модель небольшого рабочего коллектива. Сотрудники получают задания, выполняют их, иногда болеют — и мы хотим посчитать, сколько это стоит компании. Метод. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru