Форум программистов, компьютерный форум, киберфорум
C#: WPF, UWP и Silverlight
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.67/21: Рейтинг темы: голосов - 21, средняя оценка - 4.67
30 / 47 / 19
Регистрация: 23.10.2014
Сообщений: 1,001

Как сделать контейнер для чата?

26.04.2016, 13:16. Показов 4968. Ответов 35

Студворк — интернет-сервис помощи студентам
Делаю чат, мне нужен контейнер в котором будут отображаться сообщения. Это должно выглядеть как в классических чатах, т.е.: поле по типу TextBox-а многострочное, но ReadOnly чтобы можно было копировать. Сообщения будут в формате "time username> message". Но самое главное и сложное надо чтобы ник (username) был кликабельным! Т.е. он во первых должен отображаться ну примерно как ссылка, такой подчеркнутый. При клике по нему можно открыть приват. (это уже я сам дореализую понятное дело, мне бы только сделать его кликабельным) А при клике правой кнопкой по нему контекстную менюшку открыть. Подскажите как это реализовать? Только не предлагать ListBox, я уже видел такие примеры в сети! Это не то совсем, потому что это уже вообще не смотрится как чат и копировать нельзя...
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
26.04.2016, 13:16
Ответы с готовыми решениями:

приват "комната" для чата, как это сделать на сервере?
Доброго времени суток гос-да. Появилась потребность в приват "комнате" чата, в которой должно быть не более 7ми клиентов. Если кто...

Попытка сделать основу для чата
В общем есть код получения текста файла с сервера:function Dr(Encoding:TEncoding;filename:string):string; var h:THttpClient; ...

Как сделать обновление чата?
Смотрите у меня есть какое-то поле для ввода сообщения, и какое-то поле для вывода сообщений, всё уже выводиться и добавляется и чиститься,...

35
30 / 47 / 19
Регистрация: 23.10.2014
Сообщений: 1,001
28.04.2016, 12:04  [ТС]
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от novikov.ea Посмотреть сообщение
У вас не правильное понимание. Если Вы прописываете Grid, то будет создана сетка, в ячейки которой будут помещаться прописываемые элементы.
Я это отлично понимаю. Я спрашиваю как сделать так как я описал? Чтобы текст переносился под время?! Это значит что может быть мне не нужен Grid, а нужно что то еще... Я не знаю что.
Цитата Сообщение от novikov.ea Посмотреть сообщение
StringFormat="{0} {1} {2}"
Вот так явно нельзя задавать. Ошибка будет.

Добавлено через 3 минуты
И кстати вот это то что вы предлагаете: какой контейнер??? У меня же список этих сообщений, а не одно...
0
Эксперт .NET
 Аватар для novikov.ea
1857 / 1363 / 429
Регистрация: 10.06.2011
Сообщений: 2,136
28.04.2016, 13:20
Цитата Сообщение от Dark Byte Посмотреть сообщение
У меня же список этих сообщений, а не одно
Ну, так я Вам содержимое для ItemTemplate написал
0
30 / 47 / 19
Регистрация: 23.10.2014
Сообщений: 1,001
28.04.2016, 15:20  [ТС]
Цитата Сообщение от novikov.ea Посмотреть сообщение
Ну, так я Вам содержимое для ItemTemplate написал
Зачем? У меня уже есть содержимое для ItemTemplate.

Добавлено через 49 секунд

Не по теме:

Кто бы мог подумать что на казалось бы таком многогранном WPF такая проблема написать обычный чат... Я уже начинаю думать что это вообще нереально.



Добавлено через 1 час 57 минут
novikov.ea, ну куда же вы ушли я без вас не справлюсь.

Еще раз упорядочим вопросы, чтобы не терялись:

1. Идеальный вариант был бы с FlowDocument, но нужна идея как реализовать биндинг к нему и без таблиц.

2. Я сделал в принципе какой никакой шаблон ItemTemplate:
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<ItemsControl ItemsSource="{Binding Path=List}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="1.75*"/>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="10*"/>
                </Grid.ColumnDefinitions>
                
                <TextBox Text="{Binding Path=Time, StringFormat=HH:mm}" BorderThickness="0" IsReadOnly="True" Grid.Column="0"/>
                <TextBox Text="{Binding Path=Nick}" BorderThickness="0" IsReadOnly="True" Grid.Column="1"/>
                <TextBox Text="{Binding Path=Message}" TextWrapping="WrapWithOverflow" BorderThickness="0" IsReadOnly="True" Grid.Column="2"/>
            </Grid>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>
Там, пусть и нельзя выделить все сразу, а только отдельно время, отдельно ник, отдельно сообщение, но зато хотя бы можно повесить на ник команду и стиль, так что хотя бы визуально все отображается почти правильно. Одно но! Надо сделать как то чтобы текст сообщения переносился не под себя, а под время. Я понимаю что это грид это таблица, но может это не гридом сделать, а как то еще? Ну не вариант же чтоб оно так отображалось!!! А ваш вариант novikov.ea, во первых как я уже сказал не скомпилировался, во вторых, если уж я вынужден выбирать между возможностью выделять элементы и кликабельным ником, то может стоит попытаться не отказываться и от того и от другого?

3. Мне нужен способ хотя бы просто вывести обычный список строк. Безо всяких дополнительных моделей. Просто объявить: List<string> MessageList { get; } и прибиндить. Чтобы выводилить они просто как в обычный многострочный TextBox, разделенные символом новой строки. Форматирование (время, ник, сообщение) все будет в строках делаться уже при добавлении в список. Основное отличие этого способа от остальных то что тут хотя бы можно было бы свободно выделять любую часть текста... Т.е. обычное текстовое поле. Поэтому всякие там ItemsControl-ы и ListBox-ы тут не подойдут.
0
Эксперт .NET
 Аватар для novikov.ea
1857 / 1363 / 429
Регистрация: 10.06.2011
Сообщений: 2,136
28.04.2016, 15:55
Цитата Сообщение от Dark Byte Посмотреть сообщение
Идеальный вариант был бы с FlowDocument, но нужна идея как реализовать биндинг к нему и без таблиц.
Можете попробовать сделать не на основе таблицы, а на основе RichTextBox'а. Возьмите за основу пример, который я вам давал по ссылке. Измените код класса ItemsContent. Вместо таблицы создавайте RichTextBox. Для каждого элемента из ItemsSource в качестве ItemContainer создавайте Paragraph. А в качестве DataTemplate в xaml прописывайте Span, содержащий ваши три Run с текстом. В этом случае и текст можно будет всплошную выделять, и текст сообщения будет располагаться под временем
0
30 / 47 / 19
Регистрация: 23.10.2014
Сообщений: 1,001
28.04.2016, 16:07  [ТС]
Цитата Сообщение от novikov.ea Посмотреть сообщение
Вместо таблицы создавайте RichTextBox. Для каждого элемента из ItemsSource в качестве ItemContainer создавайте Paragraph.
Не понял. RichTextBox внутри элемента flowdoc:Fragment как в примере? Там он не хочет создаваться... А если убрать flowdoc:Fragment то RichTextBox создается, но внутри него нельзя Paragraph объявить.
0
Эксперт .NET
 Аватар для novikov.ea
1857 / 1363 / 429
Регистрация: 10.06.2011
Сообщений: 2,136
28.04.2016, 16:50

Не по теме:

Смерть находится на конце иглы, игла в яйце, яйцо в утке, утка в зайце, заяц в ларце


Paragraph в BlockCollection, BlockCollection во FlowDocument (свойство Blocks), FlowDocument в RichTextBox (свойство Document)
0
30 / 47 / 19
Регистрация: 23.10.2014
Сообщений: 1,001
28.04.2016, 16:56  [ТС]
novikov.ea, фух запутал в конец.
XML
1
2
3
4
5
6
7
8
9
<RichTextBox>
    <RichTextBox.Document>
        <FlowDocument>
            <FlowDocument.Blocks>
                <Paragraph/>
            </FlowDocument.Blocks>
        </FlowDocument>
    </RichTextBox.Document>            
</RichTextBox>
Так? А теперь как это соотнести с примером? Потому что вот хотя бы начиная сверху примера: внутри FlowDocument было flowdoc:ItemsContent, а у вас Blocks...
0
Эксперт .NET
 Аватар для novikov.ea
1857 / 1363 / 429
Регистрация: 10.06.2011
Сообщений: 2,136
28.04.2016, 17:17
Цитата Сообщение от Dark Byte Посмотреть сообщение
А теперь как это соотнести с примером?
Я для вас уже почти всё расписал.
1) Класс ItemsContent будет наследоваться не от Section, а от ContentControl
2) ItemsContent должен создать и засунуть себе в Content RichTextBox
3) Для каждого элемента из ItemsSource ItemsContent будет создавать не TableRow, а Paragraph. И засовывать в него Span с тремя Run (которые должны парситься из DataTemplate). В Paragraph.DataContext нужно задать этот элемент из ItemsSource
4) Затем этот Paragraph нужно будет положить в RichTextBox.Document.Blocks
0
30 / 47 / 19
Регистрация: 23.10.2014
Сообщений: 1,001
28.04.2016, 18:06  [ТС]
Цитата Сообщение от novikov.ea Посмотреть сообщение
1) Класс ItemsContent будет наследоваться не от Section, а от ContentControl
Вы сейчас говорите о наследовании в C# или о вложенности тэгов? Если о наследовании то тогда надо будет исправлять кучу ошибок в классе ItemsContent (я попробовал) которые я не знаю как исправить. А если о вложенности то я и вовсе ничего не понимаю. В примере не было в XAML никакого Section.
Цитата Сообщение от novikov.ea Посмотреть сообщение
2) ItemsContent должен создать и засунуть себе в Content RichTextBox
Опять путаница какая то. Исходя из того что вы говорили ранее сначала должен идти RichTextBox а потом FlowDocument, но просто так ItemsContent нельзя повесить, он должен быть внутри FlowDocument...

Короче! Так можно гадать неделю. Может вы просто напишете кодом что вы имеете ввиду? Я не понимаю вас...
0
Эксперт .NET
 Аватар для novikov.ea
1857 / 1363 / 429
Регистрация: 10.06.2011
Сообщений: 2,136
28.04.2016, 18:31
Цитата Сообщение от Dark Byte Посмотреть сообщение
Вы сейчас говорите о наследовании в C# или о вложенности тэгов?
О наследовании
Цитата Сообщение от Dark Byte Посмотреть сообщение
Если о наследовании то тогда надо будет исправлять кучу ошибок в классе ItemsContent
Понятное дело, что надо исправлять) Нужно запрограммировать свой контрол со своей логикой. А ItemsContent из примера - это будет просто наглядный пример, как примерно делать.
Цитата Сообщение от Dark Byte Посмотреть сообщение
сначала должен идти RichTextBox а потом FlowDocument
Всё верно
Цитата Сообщение от Dark Byte Посмотреть сообщение
просто так ItemsContent нельзя повесить, он должен быть внутри FlowDocument
Ответ на это: Класс ItemsContent будет наследоваться не от Section, а от ContentControl. Следовательно он будет обычным, а не потоковым контролом, и не должен лежать во FlowDocument.
0
30 / 47 / 19
Регистрация: 23.10.2014
Сообщений: 1,001
28.04.2016, 20:57  [ТС]
novikov.ea, а можете помочь с написанием собственно этого контрола? А то я могу только разве что убрать все где ошибки падают:
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
using System;
using System.Collections;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
 
namespace FlowDocumentApp.FlowDocuments
{
    public class ItemsContent : ContentControl//Section
    {
        private static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register("ItemsSource", typeof(IEnumerable), typeof(ItemsContent), new PropertyMetadata(OnItemsSourceChanged));
        private static readonly DependencyProperty ItemTemplateProperty = DependencyProperty.Register("ItemTemplate", typeof(DataTemplate), typeof(ItemsContent), new PropertyMetadata(OnItemTemplateChanged));
        private static readonly DependencyProperty ItemsPanelProperty = DependencyProperty.Register("ItemsPanel", typeof(DataTemplate), typeof(ItemsContent), new PropertyMetadata(OnItemsPanelChanged));
 
        public ItemsContent()
        {
            //Helpers.FixupDataContext(this);
            Loaded += ItemsContent_Loaded;
        }
 
        private void ItemsContent_Loaded(object sender, RoutedEventArgs e)
        {
            GenerateContent(ItemsPanel, ItemTemplate, ItemsSource);
        }
 
        public IEnumerable ItemsSource
        {
            get { return (IEnumerable)GetValue(ItemsSourceProperty); }
            set { SetValue(ItemsSourceProperty, value); }
        }
 
        public DataTemplate ItemTemplate
        {
            get { return (DataTemplate)GetValue(ItemTemplateProperty); }
            set { SetValue(ItemTemplateProperty, value); }
        }
 
        public DataTemplate ItemsPanel
        {
            get { return (DataTemplate)GetValue(ItemsPanelProperty); }
            set { SetValue(ItemsPanelProperty, value); }
        }
 
        private void GenerateContent(DataTemplate itemsPanel, DataTemplate itemTemplate, IEnumerable itemsSource)
        {
            //Blocks.Clear();
            if (itemTemplate != null && itemsSource != null)
            {
                FrameworkContentElement panel = null;
 
                foreach (object data in itemsSource)
                {
                    if (panel == null)
                    {
                        /*if (itemsPanel == null)
                            panel = this;
                        else*/
                        if (itemsPanel != null)
                        {
                            FrameworkContentElement p = Helpers.LoadDataTemplate(itemsPanel);
                            if (!(p is Block))
                                throw new Exception("ItemsPanel must be a block element");
                            //Blocks.Add((Block)p);
                            panel = Attached.GetItemsHost(p);
                            if (panel == null)
                                throw new Exception("ItemsHost not found. Did you forget to specify Attached.IsItemsHost?");
                        }
                    }
                    FrameworkContentElement element = Helpers.LoadDataTemplate(itemTemplate);
                    element.DataContext = data;
                    Helpers.UnFixupDataContext(element);
                    if (panel is Section)
                        ((Section)panel).Blocks.Add(Helpers.ConvertToBlock(data, element));
                    else if (panel is TableRowGroup)
                        ((TableRowGroup)panel).Rows.Add((TableRow)element);
                    else
                        throw new Exception(String.Format("Don't know how to add an instance of {0} to an instance of {1}", element.GetType(), panel.GetType()));
                }
            }
        }
 
        private void GenerateContent()
        {
            GenerateContent(ItemsPanel, ItemTemplate, ItemsSource);
        }
 
        private void OnItemsSourceChanged(IEnumerable newValue)
        {
            if (IsLoaded)
                GenerateContent(ItemsPanel, ItemTemplate, newValue);
        }
 
        private void OnItemTemplateChanged(DataTemplate newValue)
        {
            if (IsLoaded)
                GenerateContent(ItemsPanel, newValue, ItemsSource);
        }
 
        private void OnItemsPanelChanged(DataTemplate newValue)
        {
            if (IsLoaded)
                GenerateContent(newValue, ItemTemplate, ItemsSource);
        }
 
        private static void OnItemsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((ItemsContent)d).OnItemsSourceChanged((IEnumerable)e.NewValue);
        }
 
        private static void OnItemTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((ItemsContent)d).OnItemTemplateChanged((DataTemplate)e.NewValue);
        }
 
        private static void OnItemsPanelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((ItemsContent)d).OnItemsPanelChanged((DataTemplate)e.NewValue);
        }
    }
}
Хз будет ли этого достаточно... Еще я не пойму где должны лежать <flowdoc:ItemsContent.ItemsPanel> и <flowdoc:ItemsContent.ItemTemplate>? Т.е. по примеру они лежали в ItemsContent, но теперь же в нем RichTextBox лежит...

Добавлено через 1 час 59 минут
novikov.ea, я правда не знаю как его написать! Я вообще не понимаю всю вот эту иерархию которую вы предложили, я в ней запутался... Мне бы главное чтоб заработало! Помогите пожалуйста написать этот контрол и покажите уже кодом xaml как именно вы говорите надо это все разместить!!!
0
Эксперт .NET
 Аватар для novikov.ea
1857 / 1363 / 429
Регистрация: 10.06.2011
Сообщений: 2,136
29.04.2016, 00:33
Лучший ответ Сообщение было отмечено Dark Byte как решение

Решение

Вот вам готовое решение. Говнокод, дублирование кода и прочие мелочи отрефакторите сами.
Вложения
Тип файла: rar FlowItemsControlApp.rar (76.5 Кб, 18 просмотров)
2
30 / 47 / 19
Регистрация: 23.10.2014
Сообщений: 1,001
29.04.2016, 07:17  [ТС]
novikov.ea, спасибо работает!!! Скажите а можно только сделать не на базе FlowDocumentPageViewer, а на базе FlowDocumentScrollViewer? Никак не нахожу где тут это указано, а вот этот лишний интерфейс мне совсем не нужен... Все вот эти поиск, страницы, масштаб убрать бы еще.
0
Эксперт .NET
 Аватар для novikov.ea
1857 / 1363 / 429
Регистрация: 10.06.2011
Сообщений: 2,136
29.04.2016, 07:53
Dark Byte, Вы хотите, чтобы я за Вас погуглил, как это убрать?)
0
30 / 47 / 19
Регистрация: 23.10.2014
Сообщений: 1,001
29.04.2016, 07:57  [ТС]
novikov.ea, ну в общем.... Вы же написали контрол, вы лучше понимаете как это убрать.

Добавлено через 1 минуту
Я знаю только что эти вещи от PageViewer-а, а мне нужен ScrollViewer. Гугл мне другого и не скажет. А у вас я вообще не нахожу где это указывается...
0
Эксперт .NET
 Аватар для novikov.ea
1857 / 1363 / 429
Регистрация: 10.06.2011
Сообщений: 2,136
29.04.2016, 09:13
Стиль находится в файле Generic.xaml. Я не знаю, как эту полосу убрать. Попробуйте изменить FlowDocument, находящийся в шаблоне стиля.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
29.04.2016, 09:13

Как сделать форум на сайте ? на подобии чата ?
КАК сделать форум на сайте ???? на подобии чата ???

Заменить контейнер vector, использовавшийся для хранения текстовых строк (листинг 2.3), на контейнер list
Здравствуйте форумчане, может кто объяснить как делать это задание и что собственно мы тут вообще делаем. сам листинг 2.3 ниже ...

Как сделать в объекте ссылку на объект - контейнер?
есть такой код: function photo(jObj){ this.img = jObj.find('.photo-site-prv'); var src = this.img.attr('src').split('/'); ...

Как сделать удаление чаттера из чата, если он ничего ни делает 3 мин.?
Я знаю что нужно использовать сессии и куки, только я незнаю как именно их использывать, должно получиться примерно так: если чаттер не...

Как сделать свой контейнер совместимым с std::allocator?
Как сделать свой контейнер совместимым с std::allocator?


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

Или воспользуйтесь поиском по форуму:
36
Ответ Создать тему
Новые блоги и статьи
Запустил конкурс "тем и промптов для текстовых квестов созданных почти чисто ИИ"
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