Страницы

Поиск по вопросам

воскресенье, 1 декабря 2019 г.

Отрисовка пузырей сообщений в чате на WPF

#c_sharp #wpf #net #controls


Нужно нарисовать средствами WPF что-то подобное


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

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

В общем, уважаемые гуру, мне очень нужен ваш совет по поводу того, какие средства
использовать в WPF для этих целей.

Подскажите, в каком направлении искать, а я уж постараюсь двигаться самостоятельно.
После самостоятельного поиска, который дал не очень много, сформировались такие вопросы:


Какой контрол можно перерисовать в форме вот этих белых и зеленых
фигур? Как это собственно делают нормальные люди (контрол кастомной
формы)? 
как внутрь поместить текст? 
как рассчитать количество
сообщений, которые помещаются на одну страничку.


И еще одно. У приложения должна быть страничная навигация (если я правильно понимаю
смысл этого понятия)
Нужна кнопка, которая будет делать переход на следующую страничку и на предыдущую.
как когда кликаешь NEXT и открывается следующий слайд.
    


Ответы

Ответ 1



Вам не нужен контрол кастомной формы. Вам просто нужно отрисовать облако с хвостиком нужного размера, и наложить текст внутри. Возьмём исходную картинку и уберём из неё текст: Это будет наш фон. Только надо, чтобы он изменял размеры не одинаково. Стандартная идея состоит в выделении нескольких областей: Угловые области не должны меняться вовсе, верхняя и нижняя боковые должны растягиваться по горизонтали, левая и правая боковые — по вертикали, а центральная — в обеих направлениях. Раз верхняя и нижняя боковые картинки будут всё равно растягиваться в ширину, можно сделать их шириной в один пиксель, и точно так же левую и правую боковые — высотой в один пиксель. Центральную область можно вовсе сделать 1х1. Для реализации этого в WPF заведём UserControl: Теперь, нужно наложить на это текст. Абсолютно правильным путём было бы сделать декоратор с только что созданным контролом в фоне, но для этого нужны продвинутые знания WPF, так что мы пойдём более простым путём: заведём ещё один UserControl. Небольшая хитрость заключается в том, что облако должно быть такого же размера, как и текст, так что придётся использовать Binding, и чтобы Bubble не влиял сам на лэйаут, засунем его, например, в Canvas: В code-behind нужно положить свойство Text: public partial class BubbleWithText : UserControl { public BubbleWithText() { InitializeComponent(); } #region dp string Text public string Text { get { return (string)GetValue(TextProperty); } set { SetValue(TextProperty, value); } } public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(BubbleWithText)); #endregion } Теперь можно засунуть наши элементы в StackPanel: и получить следующее: Разумеется, исходные картинки лучше нарисовать самостоятельно (или потребовать у дизайнера), и ни в коем случае не сохранять в JPEG. Если вы хотите сделать более правильно, используйте декоратор: public class BubbleDecorator : Decorator { Bubble bubble = new Bubble(); public BubbleDecorator() { bubble.SetBinding(Bubble.WidthProperty, new Binding("ActualWidth") { Source = this }); bubble.SetBinding(Bubble.HeightProperty, new Binding("ActualHeight") { Source = this }); } protected override Visual GetVisualChild(int index) { if (Child != null) { if (index == 0) return bubble; if (index == 1) return Child; } throw new IndexOutOfRangeException("Wrong child index"); } protected override Size ArrangeOverride(Size arrangeSize) { bubble.Arrange(new Rect(arrangeSize)); return base.ArrangeOverride(arrangeSize); } protected override int VisualChildrenCount { get { return Child == null ? 0 : 2; } } } Получаем такой XAML:

Ответ 2



Идею с разрезанием картинки на 9 частей @Vlad разъяснил. Теперь я покажу, как то же самое сделать самым простым способом и в векторе. Отрисовка примитивная, в качестве примера. Обратите внимание на использование исключительно стилей, шаблонов и биндингов к свойствам контрола. Никакого кода в C#, никаких пользовательских контролов, никаких декораторов; на выходе только ContentControl с двумя стилями: для левого и правого пузыря. Выглядит результат так:

Ответ 3



Вот вариант с декоратором на основе решения @VladD (пишу по памяти, возможны опечатки): Использование: Привет, мир!

Комментариев нет:

Отправить комментарий