Форум программистов, компьютерный форум, киберфорум
C#: WPF, UWP и Silverlight
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.98/40: Рейтинг темы: голосов - 40, средняя оценка - 4.98
2 / 2 / 0
Регистрация: 03.05.2021
Сообщений: 26
WPF

Заполнение вкладок TabItem данными из БД WPF

03.05.2021, 21:07. Показов 9022. Ответов 66

Студворк — интернет-сервис помощи студентам
Опирался на пост Вывод данных из БД в разные TabItem
Допустим, есть база данных с таблицами "Уровень", "Вопросы", "Теория" и "Главы", связи все настроил. Также есть проект WPF с окном, на котором расположены два TabItem'а, на которых располагаются поочередно теория и вопросы к ней. Допустим, человек выбирает какую-нибудь главу, к которой в бд относятся какая-нибудь теория и вопросы к ней. Ему выводится теория на первой вкладке, а за ней на второй (или условно третьей и четвертой) отображаются задания. Была мысль выводить теорию с помощью элемента WebBrowser, просто открывая различные html страницы, однако вариант с бд кажется интереснее. Если есть какие-либо замечания по спроектированной базе данных - буду рад выслушать!

0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
03.05.2021, 21:07
Ответы с готовыми решениями:

Переключение вкладок в tabcontrol при клике на элемент внутри tabitem
Есть tabcontrol и в каждом tabitem имеется textbox и colorpicker, если ткнуть в colorpicker, то откроется компонент выбора цвета, но...

Wpf скрыть TabItem у TabControl
хочу скрыть один таб итем. указываю <TabControl Grid.Row="0"> <TabItem Visibility="Hidden"> скрывается только кнопка...

WPF Custom TabItem in TabControl - UserControl vs ControlTemplate (DataTemplate)
В моем приложении будут динамически добавляться вкладки в TabControl и динамически удаляться. Для этого хочу добавить в заголовок вкладки...

66
2 / 2 / 0
Регистрация: 03.05.2021
Сообщений: 26
14.05.2021, 16:17  [ТС]
Студворк — интернет-сервис помощи студентам
Элд Хасп, Здравствуйте! Все необходимые работы, вроде как, сделаны. Единственное что только необходимо сразу сказать - проект работает на .NET 5. Кинул Вам повторное приглашение на соавторство, поскольку пересоздавали репозиторий по некоторым обстоятельствам
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,176
Записей в блоге: 2
14.05.2021, 18:57
kMOD, Varyna, я приехал.
Завтра после обеда загружу Реп посмотрю что и как.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,176
Записей в блоге: 2
15.05.2021, 15:12
Цитата Сообщение от kMOD Посмотреть сообщение
Кинул Вам повторное приглашение на соавторство
Ок!
Посмотрел Реп.
Вы разделили на два проекта.
В одном Репозиторий в другом View и ViewModel.
Где собираетесь реализовывать Model?

Можно в отдельном проекте, можно добавить в Репозиторий.

Что нам нужно от Модели:
1) Метод возвращающий все уровни и их названия (Title);
2) Метод возвращающий описание (Descriptor) уровня по его Id;
3) Метод возвращающий все вопросы уровня с их названиями (Title);
4) Метод возвращающий описание (Descriptor) вопроса по его Id;
5) Метод получающий ответы на все вопросы уровня и возвращающий оценку.

Модели Репозитория не должны использоваться для уровня Model-ViewModel.
Но для упрощения можно так сделать.
Но можно и создать DTO или использовать кортежи.
На мой взгляд - кортежи это оптимально для этой задачи.
0
78 / 67 / 13
Регистрация: 04.10.2018
Сообщений: 330
15.05.2021, 15:25
Элд Хасп, Добрый день, это я разделил на два проекта. Так как считаю работу с БД лучше реализовывать так, а далее работать с данными только с Dto.
У меня к вам вопрос я привык использовать Service в моем понимании Service это место где мы делаем некие действия с данными Dto это что то похожее на Model? или видимо я Model путаю с Service.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,176
Записей в блоге: 2
15.05.2021, 16:39
Цитата Сообщение от Varyna Посмотреть сообщение
считаю работу с БД лучше реализовывать так, а далее работать с данными только с Dto
Согласен.
Тогда лучше Модель тоже разместить в Репозитории.
В ней не будет никакой Бизнес Логики, только работа с Репом и передача данных в VM.
DTO как мне кажется для данной задачи проще реализовать на кортежах.
В каждом типе 1...3 свойства (или поля).
Не вижу необходимости ради этого в построение целой кучи специальных классов.

Добавлено через 4 минуты
Цитата Сообщение от Varyna Посмотреть сообщение
У меня к вам вопрос я привык использовать Service в моем понимании Service это место где мы делаем некие действия с данными Dto это что то похожее на Model? или видимо я Model путаю с Service.
С точки зрения MVVM всё, что работает с "настоящими" Данными относится к слою Модели: Бизнес Логика, различные Сервисы, Репозиторий и др.

К View относится реализация самого GUI.

К VM состыковка View и Модель, в том числе различные типы предназначенные для представления в GUI, конвертация типов Модели в эти типы, какие-то сервисы этого уровня.

Добавлено через 2 минуты
То есть это зависит от того что делает с DTO ваш сервис.
Если он преобразует иммутабельный DTO в какой-то мутабельный тип с дополнительными свойствами для использования в GUI - это уровень VM.
Если же он работает с Репозиторием и преобразует его сущности (модели) в DTO и обратно - это уровень Модели.

Добавлено через 4 минуты
Сам по себе DTO тип не относится к какому-то определённому уровню.
Пример, string - можно рассматривать DTO класс.
К какому уровню он относится?
Ни какому и его можно использовать всюду.

Или типы Point, Size, Rect - их так же можно использовать где угодно.

Добавлено через 3 минуты
Varyna, но в данном случае, как мне кажется, для упрощение понимания MVVM, лучше создать специальный тип (например, TestModel) и уже под его оболочкой, если нужно, обращаться к сервисам.
Тогда в основном проекте будет создан один экземпляр Модели и VM будет работать только с ним.
А все детали будут инкапсулированы за этой оболочкой.
2
78 / 67 / 13
Регистрация: 04.10.2018
Сообщений: 330
15.05.2021, 16:49
Элд Хасп, Спасибо за развернутый ответ! Я на все 100 согласен!
0
2 / 2 / 0
Регистрация: 03.05.2021
Сообщений: 26
16.05.2021, 15:23  [ТС]
Элд Хасп, Здравствуйте! Думаю, что кортежи вполне подойдут для данного примера
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,176
Записей в блоге: 2
16.05.2021, 18:59
Цитата Сообщение от kMOD Посмотреть сообщение
Думаю, что кортежи вполне подойдут для данного примера
Сможете сами (или с помощью Varyna) реализовать Модель с этими методами?
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Что нам нужно от Модели:
1) Метод возвращающий все уровни и их названия (Title);
2) Метод возвращающий описание (Descriptor) уровня по его Id;
3) Метод возвращающий все вопросы уровня с их названиями (Title);
4) Метод возвращающий описание (Descriptor) вопроса по его Id;
5) Метод получающий ответы на все вопросы уровня и возвращающий оценку.
0
2 / 2 / 0
Регистрация: 03.05.2021
Сообщений: 26
16.05.2021, 19:21  [ТС]
Элд Хасп, Признаться честно, я с моделями еще на "Вы", вряд ли справлюсь сам
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,176
Записей в блоге: 2
16.05.2021, 19:32
Цитата Сообщение от kMOD Посмотреть сообщение
Признаться честно, я с моделями еще на "Вы", вряд ли справлюсь сам
Varyna, поможете или мне самому сделать?
0
2 / 2 / 0
Регистрация: 03.05.2021
Сообщений: 26
16.05.2021, 20:41  [ТС]
Элд Хасп, Мне кажется, если мы хотим сэкономить время, то будет проще Вам сделать
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,176
Записей в блоге: 2
16.05.2021, 21:04
Цитата Сообщение от kMOD Посмотреть сообщение
если мы хотим сэкономить время,
У меня немного проблемы со временем.
Возможно получится завтра, но не обещаю.

Добавлено через 1 минуту
Как то отвечать со смарта могу, но вот ком даже времени включить нет.
0
78 / 67 / 13
Регистрация: 04.10.2018
Сообщений: 330
17.05.2021, 03:29
Элд Хасп, У меня пока с временем проблеммы. Лучше вам сделать.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,176
Записей в блоге: 2
17.05.2021, 09:24
kMOD, сделал фиксацию:
Названия классов приведены в соответствии Правилам Именования.
Добавлена Model.
Сама Модель:
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
using Entitys.Repository;
using System;
using System.Collections.Generic;
using System.Linq;
 
namespace Entitys.Model
{
    public class TestModel
    {
        //1) Метод возвращающий все уровни и их названия(Title);
        //2) Метод возвращающий описание(Descriptor) уровня по его Id;
        //3) Метод возвращающий все вопросы уровня с их названиями(Title);
        //4) Метод возвращающий описание(Descriptor) вопроса по его Id;
        //5) Метод получающий ответы на все вопросы уровня и возвращающий оценку.
 
        /// <summary>Возвращает все уровни.</summary>
        /// <returns>Последовательность кортежей id и title уровней.</returns>
        public IEnumerable<(int id, string title)> GetAllLevels()
        {
            using (var context = new ApplicationContext())
                return context.Levels
                    .ToList()
                    .Select(lvl => (id: lvl.Id, title: lvl.Title ?? string.Empty))
                    .ToList()
                    .AsReadOnly();
        }
 
 
        /// <summary>Возвращает все вопросы уровня.</summary>
        /// <param name="levelId">Id уровня.</param>
        /// <returns>Последовательность кортежей id и title вопросов.</returns>
        public IEnumerable<(int id, string title)> GetLevelQuestions(int levelId)
        {
            using (var context = new ApplicationContext())
                return context.Questions
                    .Where(qst => qst.LevelsId == levelId)
                    .ToList()
                    .Select(qst => (id: qst.Id, title: qst.Title ?? string.Empty))
                    .ToList()
                    .AsReadOnly();
        }
 
        /// <summary>Возвращает описание вопроса.</summary>
        /// <param name="questionId">Id вопроса.</param>
        /// <returns>Строку с описанием вопроса.
        /// Если оописание не найдено - возвращается <see cref="string.Empty"/>.</returns>
        public string GeQuestionDescriptor(int questionId)
        {
            using (var context = new ApplicationContext())
                return context.QuestionsDescriptors
                    .Find(questionId)
                    ?.Descriptor
                    ?? string.Empty;
        }
 
 
        /// <summary>Возвращает количество правильных ответов.</summary>
        /// <param name="levelId">Выбранный уровень.</param>
        /// <param name="answers">Последовательность кортежей id вопроса и ответа на него.</param>
        /// <returns>Возвращает кортеж: общее количество вопросов уровня и количество правильных ответов.</returns>
        /// <exception cref="Exception">Если в последовательности ответов есть Id вопроса не из этого уровня.</exception>
        public (int totalCount, int rightCount) RateAnswers(int levelId, IEnumerable<(int questionId, string answer)> answers)
        {
            using (var context = new ApplicationContext())
            {
                var questionsIds = context.Questions
                    .Where(qst => qst.LevelsId == levelId)
                    .Select(qst => qst.Id)
                    .ToHashSet();
 
                if (answers.Any(ans => !questionsIds.Contains(ans.questionId)))
                    throw new Exception("Дан ответ на вопрос не из этого уровня.");
 
                var answersquestionsIds = answers
                    .Select(ans => ans.questionId)
                    .ToHashSet();
 
                var rightAnswers = context.QuestionsAnswers
                    .Where(ans => answersquestionsIds.Contains(ans.Id))
                    .ToDictionary(ans => ans.Id);
 
                int total = 0;
 
                foreach (var ans in answers)
                {
                    if (!string.IsNullOrWhiteSpace(ans.answer) &&
                        rightAnswers.TryGetValue(ans.questionId, out var answer) &&
                        string.Equals(ans.answer, answer.Answer,StringComparison.CurrentCultureIgnoreCase))
                        total++;
                }
 
                return (questionsIds.Count, total);
            }
 
        }
 
    }
}
Можно было сделать статический класс, но в общем виде это не верно, так как в Модели могут быть и какие-то члены экземпляра: логин тестируемого, строка подключения и т.д.

Я изменил названия классов сущностей, но БД не проверял - не знаю подхватится автоматически или нет.
Если будут ошибки надо внести в БД изменения.

Пока посмотрите что сделано - будут вопросы задавайте.

Как разберётесь - перейдём к созданию View и интерфейсов VM.

Добавлено через 1 секунду
kMOD, сделал фиксацию:
Названия классов приведены в соответствии Правилам Именования.
Добавлена Model.
Сама Модель:
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
using Entitys.Repository;
using System;
using System.Collections.Generic;
using System.Linq;
 
namespace Entitys.Model
{
    public class TestModel
    {
        //1) Метод возвращающий все уровни и их названия(Title);
        //2) Метод возвращающий описание(Descriptor) уровня по его Id;
        //3) Метод возвращающий все вопросы уровня с их названиями(Title);
        //4) Метод возвращающий описание(Descriptor) вопроса по его Id;
        //5) Метод получающий ответы на все вопросы уровня и возвращающий оценку.
 
        /// <summary>Возвращает все уровни.</summary>
        /// <returns>Последовательность кортежей id и title уровней.</returns>
        public IEnumerable<(int id, string title)> GetAllLevels()
        {
            using (var context = new ApplicationContext())
                return context.Levels
                    .ToList()
                    .Select(lvl => (id: lvl.Id, title: lvl.Title ?? string.Empty))
                    .ToList()
                    .AsReadOnly();
        }
 
 
        /// <summary>Возвращает все вопросы уровня.</summary>
        /// <param name="levelId">Id уровня.</param>
        /// <returns>Последовательность кортежей id и title вопросов.</returns>
        public IEnumerable<(int id, string title)> GetLevelQuestions(int levelId)
        {
            using (var context = new ApplicationContext())
                return context.Questions
                    .Where(qst => qst.LevelsId == levelId)
                    .ToList()
                    .Select(qst => (id: qst.Id, title: qst.Title ?? string.Empty))
                    .ToList()
                    .AsReadOnly();
        }
 
        /// <summary>Возвращает описание вопроса.</summary>
        /// <param name="questionId">Id вопроса.</param>
        /// <returns>Строку с описанием вопроса.
        /// Если оописание не найдено - возвращается <see cref="string.Empty"/>.</returns>
        public string GeQuestionDescriptor(int questionId)
        {
            using (var context = new ApplicationContext())
                return context.QuestionsDescriptors
                    .Find(questionId)
                    ?.Descriptor
                    ?? string.Empty;
        }
 
 
        /// <summary>Возвращает количество правильных ответов.</summary>
        /// <param name="levelId">Выбранный уровень.</param>
        /// <param name="answers">Последовательность кортежей id вопроса и ответа на него.</param>
        /// <returns>Возвращает кортеж: общее количество вопросов уровня и количество правильных ответов.</returns>
        /// <exception cref="Exception">Если в последовательности ответов есть Id вопроса не из этого уровня.</exception>
        public (int totalCount, int rightCount) RateAnswers(int levelId, IEnumerable<(int questionId, string answer)> answers)
        {
            using (var context = new ApplicationContext())
            {
                var questionsIds = context.Questions
                    .Where(qst => qst.LevelsId == levelId)
                    .Select(qst => qst.Id)
                    .ToHashSet();
 
                if (answers.Any(ans => !questionsIds.Contains(ans.questionId)))
                    throw new Exception("Дан ответ на вопрос не из этого уровня.");
 
                var answersquestionsIds = answers
                    .Select(ans => ans.questionId)
                    .ToHashSet();
 
                var rightAnswers = context.QuestionsAnswers
                    .Where(ans => answersquestionsIds.Contains(ans.Id))
                    .ToDictionary(ans => ans.Id);
 
                int total = 0;
 
                foreach (var ans in answers)
                {
                    if (!string.IsNullOrWhiteSpace(ans.answer) &&
                        rightAnswers.TryGetValue(ans.questionId, out var answer) &&
                        string.Equals(ans.answer, answer.Answer,StringComparison.CurrentCultureIgnoreCase))
                        total++;
                }
 
                return (questionsIds.Count, total);
            }
 
        }
 
    }
}
Можно было сделать статический класс, но в общем виде это не верно, так как в Модели могут быть и какие-то члены экземпляра: логин тестируемого, строка подключения и т.д.

Я изменил названия классов сущностей, но БД не проверял - не знаю подхватится автоматически или нет.
Если будут ошибки надо внести в БД изменения.

Пока посмотрите что сделано - будут вопросы задавайте.

Как разберётесь - перейдём к созданию View и интерфейсов VM.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,176
Записей в блоге: 2
17.05.2021, 13:32
kMOD, по архитектуре View предполагаю три страницы:
1) Выбор уровня;
2) Вкладки с вопросами уровня. На каждой вкладке описание вопроса и поле для ввода ответа;
3) Получение результата теста: сколько правильных ответов из общего количества вопросв.

Само окно будет состоять из кнопки навигации (начать тест, получить результат, начать сначала) и региона для отображения страницы.

Теперь по интерфейсам VM:
1) Интерфейс одного уровня: Id, Title, Descriptor;
2) Выбранный уровень: одно свойство SelectedLevel;
3) Производный от 2 для выбора уровня: коллекция уровней и команда получения вопросов уровня;
4) Интерфейс одного вопроса: Id, Title, Descriptor, Answer;
5) Производный от 2: коллекция вопросов уровня и команда получения результата по тесту;
6) Производный от 2: количество вопросов уровня и количество правильных ответов и команда перехода к выбору уровня.

Добавлено через 2 часа 0 минут
Сделал фиксацию:
Добавлены интерфейсы для ViewModel.
Добавлены базовые классы для INPC и команд.
C#
1
2
3
4
5
6
7
8
9
10
namespace TabItem.ViewModelInterfaces
{
    public interface ILevelVM
    {
        int Id { get; }
        string Title { get; }
        string Descriptor { get; }
    }
 
}
C#
1
2
3
4
5
6
7
8
namespace TabItem.ViewModelInterfaces
{
    public interface ISelectedLevel
    {
        ILevelVM SelectedLevel { get; set; }
    }
 
}
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
using System.Collections.Generic;
using System.Windows.Input;
 
namespace TabItem.ViewModelInterfaces
{
    public interface ILevelsVM : ISelectedLevel
    {
        IEnumerable<ILevelVM> Levels { get; }
 
        ICommand GetQuestionsCommand { get; }
    }
 
}
C#
1
2
3
4
5
6
7
8
9
10
11
namespace TabItem.ViewModelInterfaces
{
    public interface IQuestionVM
    {
        int Id { get; }
        string Title { get; }
        string Descriptor { get; }
        string Answer { get; set; }
    }
 
}
C#
1
2
3
4
5
6
7
8
9
10
11
12
using System.Collections.Generic;
using System.Windows.Input;
 
namespace TabItem.ViewModelInterfaces
{
    public interface IQuestionsVM : ISelectedLevel
    {
        IEnumerable<IQuestionVM> Questions { get; }
        ICommand GetResultCommand { get; }
    }
 
}
C#
1
2
3
4
5
6
7
8
9
10
11
12
using System.Windows.Input;
 
namespace TabItem.ViewModelInterfaces
{
    public interface IResultVM : ISelectedLevel
    {
       int TotalCount { get; }
        int RightCount { get; }
       ICommand StartSelectLevelCommand { get; }
    }
 
}
0
2 / 2 / 0
Регистрация: 03.05.2021
Сообщений: 26
17.05.2021, 15:08  [ТС]
Элд Хасп, Ого, как много всего Есть что изучить)
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,176
Записей в блоге: 2
17.05.2021, 15:12
kMOD, сделал фиксацию:
Добавлены UserControl'ы страниц.
Для Данных времени разработки создан класс:
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.Collections.Generic;
using System.Windows.Input;
using TabItem.ViewModelInterfaces;
 
namespace TabItem.Pages
{
    static class ExampleDesignTimeData
    {
        public class LevelsVM : ILevelsVM
        {
            public ICommand GetQuestionsCommand { get; }
            public ILevelVM SelectedLevel { get; set; }
            public IEnumerable<ILevelVM> Levels { get; }
 
            public LevelsVM(IEnumerable<ILevelVM> levels)
                => Levels = levels;
        }
        public class Level : ILevelVM
        {
            public int Id { get; }
            public string Title { get; }
            public string Descriptor { get; }
 
            private Level(int id, string title, string descriptor)
            {
                Id = id;
                Title = title;
                Descriptor = descriptor;
            }
 
            public static Level First { get; } = new Level(111, "Первый", "Тест первого уровня");
            public static Level Second { get; } = new Level(222, "Второй", "Тест второго уровня");
        }
 
        public static LevelsVM LevelsDD { get; }
            = new LevelsVM(new Level[] { Level.First, Level.Second })
            { SelectedLevel = Level.First };
 
        public class Question : IQuestionVM
        {
            public int Id { get; }
            public string Title { get; }
            public string Descriptor { get; }
            public string Answer { get; set; }
 
            public Question(int id, string title, string descriptor)
            {
                Id = id;
                Title = title;
                Descriptor = descriptor;
            }
 
            public static Question First { get; } = new Question(111, "Умножение", "Дважды два?");
            public static Question Second { get; } = new Question(222, "Сложение", "Три плюс четыре");
 
        }
 
        public class QuestionsVM : IQuestionsVM
        {
            public IEnumerable<IQuestionVM> Questions { get; }
            public ICommand GetResultCommand { get; }
            public ILevelVM SelectedLevel { get; set; }
 
            public QuestionsVM(IEnumerable<IQuestionVM> questions)
            {
                Questions = questions;
            }
        }
 
        public static QuestionsVM QuestionsDD { get; }
            = new QuestionsVM(new Question[] { Question.First, Question.Second })
            { SelectedLevel = Level.First };
 
        public class Result : IResultVM
        {
            public int TotalCount { get; }
            public int RightCount { get; }
            public ICommand StartSelectLevelCommand { get; }
            public ILevelVM SelectedLevel { get; set; }
 
            public Result(int totalCount, int rightCount)
            {
                TotalCount = totalCount;
                RightCount = rightCount;
            }
        }
 
        public static Result ResultDD { get; }
            = new Result(25, 15)
            { SelectedLevel = Level.First};
    }
 
}
И три UserControl:
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
<UserControl x:Class="TabItem.Pages.SelectLevelUC"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:TabItem.Pages"
             xmlns:interfaces="clr-namespace:TabItem.ViewModelInterfaces"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800"
             Background="AliceBlue"
             d:DataContext="{x:Static local:ExampleDesignTimeData.LevelsDD}">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <TextBlock Text="Выбор уровня теста" Margin="10"
                   FontSize="20" VerticalAlignment="Center" HorizontalAlignment="Center"/>
        <UniformGrid Grid.Row="1" Columns="2">
            <ListBox Margin="10"
                     ItemsSource="{Binding Levels, Mode=OneWay}"
                     SelectedItem="{Binding SelectedLevel}"
                     DisplayMemberPath="Title"/>
            <TextBlock Text="{Binding SelectedLevel.Descriptor}"
                       Margin="10" Background="Aqua" FontSize="20"/>
        </UniformGrid>
    </Grid>
</UserControl>
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
<UserControl x:Class="TabItem.Pages.QuestionsUC"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:TabItem.Pages"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800"
             Background="LightYellow"
             d:DataContext="{x:Static local:ExampleDesignTimeData.QuestionsDD}"
             xmlns:interfaces="clr-namespace:TabItem.ViewModelInterfaces"
             >
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <TextBlock FontSize="30" HorizontalAlignment="Center"
                   Margin="10">
            <Run Text="Вопросы теста уровня '"/><Run Text="{Binding SelectedLevel.Title, Mode=OneWay}"/><Run Text="'"/>
        </TextBlock>
        <TabControl Margin="10" Grid.Row="1"
                    ItemsSource="{Binding Questions}">
            <TabControl.ItemTemplate>
                <DataTemplate DataType="{x:Type interfaces:IQuestionVM}">
                    <TextBlock Text="{Binding Title}"
                               FontSize="20"/>
                </DataTemplate>
            </TabControl.ItemTemplate>
            <TabControl.ContentTemplate>
                <DataTemplate DataType="{x:Type interfaces:IQuestionVM}">
                    <UniformGrid Columns="1">
                        <TextBlock Text="{Binding Descriptor}"
                                   FontSize="20" VerticalAlignment="Center" HorizontalAlignment="Center"
                                   Margin="5" Background="Bisque" Padding="10" TextWrapping="Wrap"/>
                        <TextBox Text="{Binding Answer}" Margin="5" Background="LightPink"
                                 Padding="10" MinWidth="100" TextWrapping="Wrap"
                                 VerticalAlignment="Center" HorizontalAlignment="Center"/>
                    </UniformGrid>
                </DataTemplate>
            </TabControl.ContentTemplate>
        </TabControl>
    </Grid>
</UserControl>
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
<UserControl x:Class="TabItem.Pages.ResultUC"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:TabItem.Pages"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800"
             Background="LightGreen"
             d:DataContext="{x:Static local:ExampleDesignTimeData.ResultDD}"
             xmlns:interfaces="clr-namespace:TabItem.ViewModelInterfaces"
             >
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <TextBlock FontSize="30" HorizontalAlignment="Center"
                   Margin="10">
            <Run Text="Результат теста уровня '"/><Run Text="{Binding SelectedLevel.Title, Mode=OneWay}"/><Run Text="'"/>
        </TextBlock>
        <UniformGrid Columns="1" Grid.Row="1">
            <TextBlock FontSize="30" VerticalAlignment="Center" HorizontalAlignment="Center">
            <Run Text="Всего вопросов:"/>
            <Run Text="{Binding TotalCount, Mode=OneWay}"/>
            </TextBlock>
            <TextBlock FontSize="30" HorizontalAlignment="Center" VerticalAlignment="Center">
            <Run Text="Правильных ответов:"/>
            <Run Text="{Binding RightCount, Mode=OneWay}"/>
            </TextBlock>
        </UniformGrid>
    </Grid>
</UserControl>
Теперь нужно добавить в Окна какой-то простой навигатор для переключения страниц.
0
2 / 2 / 0
Регистрация: 03.05.2021
Сообщений: 26
17.05.2021, 19:09  [ТС]
Элд Хасп, Прошу прощения за, быть может, слишком глупый вопрос, но что надо будет сделать в случае динамического заполнения вопросов из бд? То есть, к примеру, если я не в коде создаю пару экземпляров вопроса и пару экземпляров уровня, а хочу взять их столько, сколько у меня их описано в базе данных
Возможно, я что-то не так понял
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,176
Записей в блоге: 2
17.05.2021, 19:31
Цитата Сообщение от kMOD Посмотреть сообщение
если я не в коде создаю пару экземпляров вопроса и пару экземпляров уровня, а хочу взять их столько, сколько у меня их описано в базе данных
В коде (в классе ExampleDesignTimeData) создаётся только пример данных для удобства создания View.
Такие данные называются "Контекст Данных Времени Разработки".
Когда вы разрабатываете Окна, UserControl (как в данном случае) и др., то вам не к чему задавать привязки.
В результате все элементы пустые и вы не видите реального дизайна, компилятор (IntelliSense) выдаёт предупреждения об ошибках привязок.
Обратите внимание на префикс d: - это означает что задание значения будет игнорироваться при запуске на исполнение.

Когда Разработка View будет завершена у нас в результате будет набор интерфейсов которые должна реализовать VM.
VM - это слой посредник.
И реализовывать её лучше после реализации Model и View.
Тогда гораздо проще понять как и что надо состыковывать между собой.

Добавлено через 1 минуту
Цитата Сообщение от kMOD Посмотреть сообщение
но что надо будет сделать в случае динамического заполнения вопросов из бд?
Модель уже у нас создана.
VM будет запрашивать через методы Модели нужные данные.
0
2 / 2 / 0
Регистрация: 03.05.2021
Сообщений: 26
17.05.2021, 19:36  [ТС]
Элд Хасп,
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Когда Разработка View будет завершена у нас в результате будет набор интерфейсов которые должна реализовать VM.
VM - это слой посредник.
И реализовывать её лучше после реализации Model и View.
Тогда гораздо проще понять как и что надо состыковывать между собой.
Спасибо огромное за понятное объяснение!!
Цитата Сообщение от Элд Хасп Посмотреть сообщение
VM будет запрашивать через методы Модели нужные данные.
То есть, получается, что у нас еще не до конца доделанная версия?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
17.05.2021, 19:36

Наведение курсора на TabItem и как менять фон при нажатии на другой TabItem
Здравствуйте, у меня возникла проблема с TabItem, то есть при наведении TabItem с помощью триггера: &lt;Trigger...

Программное создание tabItem по образцу другого tabItem с контролами
Добрый вечер, уважаемые форумчане! На форме существует tabControl1. В нём уже существует tabItem1 с некими компонентами, там label1...

Автоматическое заполнение ячеек данными, взятыми из одной ячейки с динамическими данными
Добрый день! Подскажите, есть ли решение моей задачи: В одной и той же ячейке постоянно (ежесекундно) меняется число (данные...

Drop drag wpf перетаскивание вкладок ошибка
Выдает ошибку Операция недопустима, когда ItemsSource используется. Вместо этого получите доступ и измените элементы с помощью...

Таб контроль: заполнение вкладок и их создание по заданному набору названий
Доброго времени суток! В проекте использую таб контрол и вот такой текст срабатывает. TC_ITEM TabItem; TabItem.mask =...


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

Или воспользуйтесь поиском по форуму:
60
Ответ Создать тему
Новые блоги и статьи
GitHub Copilot в JetBrains: модель по умолчанию, Fix и контроль MCP
and_y87 12.10.2026
10 октября 2026 года GitHub обновил Copilot для JetBrains: добавил настройки стартовой модели, исправления из диагностики и управление автозапуском MCP. Поддержка IDE 2025. 1 прекращена — требуется. . .
GitHub Copilot в JetBrains: модель по умолчанию, Fix и контроль MCP
and_y87 12.10.2026
10 октября 2026 года GitHub обновил Copilot для JetBrains: добавил настройки стартовой модели, исправления из диагностики и управление автозапуском MCP. Поддержка IDE 2025. 1 прекращена — требуется. . .
День 5 из 28: Codex подсказывает следующий запрос
and_y87 12.10.2026
9 октября 2026 года OpenAI запустила бету Composer predictions — подсказок следующего сообщения в текущем диалоге Codex. Это помощь с формулировкой запроса, а не автоматическое продолжение задачи. . . .
Запустил конкурс "тем и промптов для текстовых квестов созданных почти чисто ИИ"
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
Раньше я радовался или получал некоторые эмоции, пусть небольшие, но всё же, от самого процесса написания кода, рекомпиляции и запуска, видя постепенное развитие программы и прочее. А теперь лень. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru