Ответы пользователя по тегу WPF
  • Как сделать подобные элементы в wpf?

    cyber_roach
    @cyber_roach
    UX дизайнер INEDIapps
    1способ
    Делается макет волн в SVG, например в InkScape (т.к. там есть редактор текстового кода (координат) для SVG)
    В WPF делается базовая разметка в левую часть ( где волны и пр) ставится Grid внутрь которого накидываете элементы Path. в свойство DATA которых прописываете поочередно код каждой "Волны" и пр элементов из SVG. (копируете из редактора кода SVG), далее задаете цвета, прозрачности и пр
    Предварительно в InkScape каждый элемент нужно вписать в прямоугольник который будет тех же пропорций что и в WPF, чтобы не мучатся с отступами в WPF (Просто создаются 2 точки по диагонали и объединяются с каждым элементом (чтобы у всех элементов было одинаковое начало координат)
    5f352e144839c343347930.png
    Свойство Data принимает класс Geometry(StreamGeometry) , который по внутренностям = SVG элементу по факту.

    2й способ (не рекомендую)
    Сделать все как в 1м только вместо Grid использовать Canvas (тогда не нужно вписывать все элементы в прямоугольник в InkScape, т.к. с этим могут возникнуть сложности)
    Минус способа - если захотите менять пропорции изображения (зумм) придется пихать Canvas во ViewBox, а данный элемент слишком малопроизводителен и часто дает не качественный рендер.
    3й способ
    Найдите в сети WPF контрол, который может прямо SVG отобразить.
    Минусом 3го способа является то, что например в 1м и 2м мы можем анимировать волны и делать реакции на мышь/тач без всяких проблем, в 3м чисто статика.
    Ответ написан
  • Как присвоить тег другому тегу?

    cyber_roach
    @cyber_roach
    UX дизайнер INEDIapps
    1) Image в Rectangle вставить нельзя. Можно вставить Image в Border, т.к Rectangle не имеет внутреннего "тега" Content presenter в темплейте.
    - то что Image будет находится внутри Border - абсолютно нормальная практика, элемент Border именно для этого и предназначен
    2) Можно использовать Image Brush и тем самым вообще отказаться от элемента Image, но чтобы понять какой подход использовать, нужно смотреть на задачу которую вы решаете.
    3) Вам явно нужно подучить WPF и XAML вы оперируете неверными понятиями.
    Глядя на ваш вопрос создается уверенное впечатление, что вы вообще не понимаете, что делаете.
    - это не теги, это элементы каждый для совершенно разных целей.
    - визуальное дерево строится по принципу не "мне хочется", а по определенным требованиям под задачу
    - Контрол, темплейт, стиль, свойства - вам нужно понять что это такое и зачем, это базовые понятия в XAML.
    Книга Мэтью Макдональда "WPF: Windows Presentation Foundation в .NET 4.5" ответит на эти и многие другие вопросы
    Ответ написан
    Комментировать
  • Почему не выводятся изображения в ListBox?

    cyber_roach
    @cyber_roach
    UX дизайнер INEDIapps
    Потому что в темплейте элемента списка ListBoxItem базово стоит TextBlock,
    а он, естественно, не умет рисовать битмапы.
    Просто сформируйте свой дата-темплейт для элемента списка.
    Ну и как бы, первый же запрос в гугл дает десяток решений:
    https://stackoverflow.com/questions/2081900/wpf-ad...
    https://ru.stackoverflow.com/questions/487722/Изоб...
    Ответ написан
    1 комментарий
  • Как отобразить вложенный datagrid в rowdetails внешнего datagrid?

    cyber_roach
    @cyber_roach
    UX дизайнер INEDIapps
    То что вы делаете - плохая практика, вы полностью убьете виртуализацию и это месиво из тяжелых контролов друг в друге будет тормозить, если данных много.
    Простое правило - 2 датагрида на вьюху - предел.(в т.ч. и по юзабилити)
    Все же RowDetails немного для другого предназначен, вывести какую-то строчку поясняющего текста, описание, статусы, не более.
    Не совсем понятно что именно вы хотите, но вроде бы вот решение вашей задачи:
    https://docs.microsoft.com/ru-ru/dotnet/framework/...

    Если хотите коллекцию в коллекции и раскрывать по клику,
    Возьмите какой-нибудь более продвинутрый грид с группировкой.
    Или вот руководство как это сделать на стандартных элементах
    https://docs.microsoft.com/ru-ru/dotnet/framework/...
    Ответ написан
    Комментировать
  • Как убрать стандартное свечение у окна программы в WPF?

    cyber_roach
    @cyber_roach
    UX дизайнер INEDIapps
    За рамку стандартных окон отвечает ОС, а не WPF,
    но её можно изменить или убрать, читайте тут:
    https://docs.microsoft.com/ru-ru/dotnet/api/system...
    Ответ написан
    1 комментарий
  • Курсы по wpf от ITVDN хорошие?

    cyber_roach
    @cyber_roach
    UX дизайнер INEDIapps
    Что ж вы, молодёжь, гонитесь за" видосиками"-то все время.

    1) WPF: Windows Presentation Foundation в .NET 4.5 с примерами на C# 5.0 для профессионалов
    за авторством Мэтью Мак-Дональда
    (Ничего лучше для старта на WPF не придумано)
    2) CLR via C#. Программирование на платформе Microsoft.NET Framework 4.5 на языке C#
    Автор Рихтер Джеффри
    (а это уже для общего более глубокого понимания всей .net платформы).

    Просмотр видео же дольше занимает времени чем чтение (т.к. в книгах легко пропускать "воду", которой там как правило в разы меньше).

    Ну и конечно же документация.
    В официальной документации вообще есть ответы на любые ваши вопросы в 99% случаев.
    https://docs.microsoft.com/ru-ru/visualstudio/desi...
    Ответ написан
    1 комментарий
  • Не удалось разрешить ресурс "ApplicationPageBackgroundThemeBrush"?

    cyber_roach
    @cyber_roach
    UX дизайнер INEDIapps
    1) Поставить IDE с нормальным языком интерфейса (английским)
    уже на этом этапе ошибки начнут гуглится и скорее всего вы найдете решение самостоятельно.
    2) Давать больше информации о том что вы пытаетесь сделать и как, все ясновидящие в летних отпусках.
    Потому что ответ на ваш вопрос в текущем виде:
    -Ошибка говорит о том что не удалось разрешить ресурс. Исправить - дать возможность его разрешить.
    Ответ написан
    Комментировать
  • Как достать все элементы из wrappanel?

    cyber_roach
    @cyber_roach
    UX дизайнер INEDIapps
    Присвойте ресурс Background или стиль элементу ссылающийся на Background
    далее просто меняйте когда нужно цвет у ресурса
    Примерный код:

    App.xaml
    <Color x:Key="DecorateColor">#FF005087</Color>
    <SolidColorBrush x:Key="BackgroundBrush" Color="{DynamicResource DecorateColor}"/>


    элементы где меняем цвет, например внутри стиля
    <Border Background="{StaticResource BackgroundBrush}"/>


    изменение цвета ресурса
    Color decorateColor = Color.Color.FromArgb(255, 136, 0, 255);
    Application.Current.Resources["DecorateColor"] = decorateColor;


    Если использовать MVVM, то можно и через StaticResource решить.

    Но это подход "В лоб", более верным будет через состояние стиля, но это вам сначала изучить Trigger (для конкретно этого случая DataTrigger) и MVVM.
    Ответ написан
    Комментировать
  • Как сделать event в wpf асинхронным?

    cyber_roach
    @cyber_roach
    UX дизайнер INEDIapps
    Стандартные методы не подошли?
    https://docs.microsoft.com/ru-ru/dotnet/csharp/pro...
    Ответ написан
    Комментировать
  • Как оптимизировать рисование линий в WPF?

    cyber_roach
    @cyber_roach
    UX дизайнер INEDIapps
    От нескольких тысяч все что угодно будет тормозить
    Направление указали уже вам, дополню:
    Чтобы не скушать всю оперативу и проц
    читайте про BitmapCache
    https://docs.microsoft.com/ru-ru/dotnet/api/system...
    и RenderTargetBitmap
    https://docs.microsoft.com/ru-ru/dotnet/api/system...
    в UWP кеширование на более верхнем уровне реализовано, там попроще, но в WPF тоже можно сделать хорошо.
    Алгоритм вкратце:
    2 слоя - верхний -там где тыкаете мышкой
    и нижний - кеш
    Добавили линию (на верхнем слое) - рендерите в картинку (верх+низ) - отрисовываете эту картинку на нижнем слое (например через ImageBrush), линию на верхнем удаляете.
    Т.е. как только пользователь закончил фигуру/действие - кешируете.
    Если нужен интерактив на уже нарисованном (например узлы точек подсвечивать), тут сложнее, но тоже возможно (запоминать коодридинаты узлов и при нахождении там мыши - создавать Xaml объект.)
    С интерактивом в подобных алгоритмах как правило много математики.

    Т.е. у вас в оперативной памяти всегда 1 картинка + сколько-то объектов - полилиний.

    К слову, через кеширование кроме рисования можно делать довольно производительные анимации, производительный зумминг, производительный скролл…

    Есть еще вариант: реализовать рисование на DirectX на C++ и поместить контрол. Более нативно и производительнее.

    P/S
    свойсвто IsHitTestVisible
    https://docs.microsoft.com/ru-ru/dotnet/api/system...
    позволяет не реагировать объекту на мышь (т.е. отключает интерактив) это полезно для объектов фона, сильно бустит производительность.
    (т.к. по умолчанию WPF определяет все события интерактива на всех объектах, а их может быть бесчисленное множество, и далеко не на всех нужно иметь реакцию на нажатие/OnMouseMove)
    Ответ написан
    Комментировать
  • Почему программа не находит ресурс?

    cyber_roach
    @cyber_roach
    UX дизайнер INEDIapps
    вот
    Uri uri = new Uri("pack://application:,,,/img1.jpg");

    На внимательность )
    Ответ написан
  • Как поменять цвет заднего фона у активного TabItem?

    cyber_roach
    @cyber_roach
    UX дизайнер INEDIapps
    Все логично.
    Вы же не поменяли цвет состояний (over select и пр...)

    WPF не про смену цвета элемента через базовые свойства элемента.
    WPF это про стили и язык разметки интерфейса (XAML)

    В базовом виде стили выглядят как-то так:
    (можете просто скопировать всё на любую форму в проекте и заработает)

    <Grid>
            <Grid.Resources>
                <ResourceDictionary>
                    <Style  TargetType="{x:Type TabItem}">
                        <Setter Property="OverridesDefaultStyle" Value="True"/>
                        <Setter Property="SnapsToDevicePixels" Value="True"/>
                        <Setter Property="Foreground" Value="White"/>
                        <Setter Property="Background" Value="#FF7C0000"/>
                        <Setter Property="BorderBrush" Value="Black"/>
                        <Setter Property="Height" Value="32"/>
                        <Setter Property="Template">
                            <Setter.Value>
                                <ControlTemplate TargetType="{x:Type TabItem}">
                                    <Border x:Name="Border" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="1" Margin="0,0,-1,0">
                                        <Grid >
                                            <Rectangle x:Name="interactive" Opacity="0.3"/>
                                            <ContentPresenter HorizontalAlignment="Center" Margin="12,2,12,2" x:Name="ContentSite" VerticalAlignment="Center" RecognizesAccessKey="True" ContentSource="Header" />
                                        </Grid>
                                    </Border>
                                    <ControlTemplate.Triggers>
                                        <Trigger Property="IsSelected" Value="True">
                                            <Setter Property="Panel.ZIndex" Value="100"/>
                                            <Setter Property="Background" Value="Black" />
                                        </Trigger>
                                        <MultiTrigger>
                                            <MultiTrigger.Conditions>
                                                <Condition Property="IsMouseOver" Value="True"/>
                                                <Condition Property="Selector.IsSelected" Value="False"/>
                                            </MultiTrigger.Conditions>
                                            <Setter Property="Fill" Value="Black" TargetName="interactive"/>
                                        </MultiTrigger>
                                        <Trigger Property="IsEnabled" Value="False">
                                            <Setter Property="Opacity" Value="0.5" TargetName="interactive" />
                                            <Setter Property="Fill" Value="Black" TargetName="interactive" />
                                            <Setter Property="Background" Value="White"/>
                                            <Setter Property="Foreground" Value="DarkGray"/>
                                        </Trigger>
                                    </ControlTemplate.Triggers>
                                </ControlTemplate>
                            </Setter.Value>
                        </Setter>
                    </Style>
                    <Style TargetType="{x:Type TabControl}">
                        <Setter Property="Background" Value="Black"/>
                        <Setter Property="Template">
                            <Setter.Value>
                                <ControlTemplate TargetType="{x:Type TabControl}">
                                    <Grid KeyboardNavigation.TabNavigation="Local">
                                        <Grid.RowDefinitions>
                                            <RowDefinition Height="Auto"/>
                                            <RowDefinition Height="*"/>
                                        </Grid.RowDefinitions>
                                        <TabPanel Grid.Row="0" IsItemsHost="True" Panel.ZIndex="1" KeyboardNavigation.TabIndex="1"/>
                                        <Border Padding="12" Background="{TemplateBinding Background}"
                                                    Grid.Row="1"  KeyboardNavigation.DirectionalNavigation="Contained" KeyboardNavigation.TabNavigation="Local" KeyboardNavigation.TabIndex="2">
                                            <ContentPresenter x:Name="PART_SelectedContentHost" ContentSource="SelectedContent"/>
                                        </Border>
                                    </Grid>
                                </ControlTemplate>
                            </Setter.Value>
                        </Setter>
                    </Style>
                </ResourceDictionary>
            </Grid.Resources>
            
            <TabControl Margin="10" >
                <TabItem Header="Файловая система">
                        <TextBlock>Вкладка 1</TextBlock>
                </TabItem>
                <TabItem Header="Еще одна система">
                        <TextBlock> Вкладка 2</TextBlock>
                </TabItem>
                <TabItem Header="Мегасистема">
                        <TextBlock> Вкладка 3</TextBlock>
                </TabItem>
                <TabItem Header="Суперсистема" IsEnabled="False">
                        <TextBlock> Вкладка в дисабле</TextBlock>
                </TabItem>
            </TabControl>
        </Grid>


    В данном примере я определил стили внутри Grid
    Это значит все таб-контролы внутри этого грида будут использовать этот внешний вид.
    Можно так же определить стиль на уровне окна или на уровне приложения (в App.xaml)
    Можно именовать стили (без имени = по умолчанию)

    Выглядит живьем все вот так:
    cuzfqh6sokmhzyh2opaumtxfpa8.png

    Соответственно после того как стиль есть, уже можно переопределить в нем базовые свойства как надо через Setter'ы

    Данная строка задает переопределение всех свойств базового стиля (ну или можно их все вручную переписать):
    <Setter Property="OverridesDefaultStyle" Value="True"/>


    А это чтобы по пикселям выровнять:
    <Setter Property="SnapsToDevicePixels" Value="True"/>


    Таким способом можно связывать отдельный компонент внутри стиля с базовым свойством:
    Background="{TemplateBinding Background}"

    А этот компонент я добавил как пример :
    <Rectangle x:Name="interactive" Opacity="0.3"/>
    Показать что интерактивные состояния можно как угодно реализовывать и что структура компонента может быть различной. (где -то у загажнике у меня валяется Tab-Control в виде круга (как у железного человека прям с радиальной расстановкой tabItem'ов)

    с помощью Trigger'ов можно делать ракцию изменений свойств.
    Также специально сделал Овер мыши через мультитриггер, для понимания как такие использовать.
    Можно сюда еще анимации добавлять.
    А можно вообще без тригеров через VisualState добавлять интерактив, принципы схожи.

    Грамотное применение стилей дает возможность не перегружать верстку страниц, визуал, отсупы, сетка все автоматом подтаскивается, что видно в самом конце кода, сами табы оформлены по минималу
    Ответ написан
  • Как реализовать LazyLoad у TreeView?

    cyber_roach
    @cyber_roach
    UX дизайнер INEDIapps
    Чем пример с MSDN не устроил ?
    https://docs.microsoft.com/ru-ru/dotnet/framework/...

    Есть момент - при наличии некоторых условий виртуализация отключается:
    - если контейнеры элементов добавляются напрямую к элементу управления ItemsControl.
    - если объект ItemsControl содержит контейнеры элементов различных типов.
    - если для прикрепленного свойства VirtualizingStackPanel.IsVirtualizing установлено значение false
    - если для прикрепленного свойства ScrollViewer.CanContentScroll установлено значение false

    Можно еще взять любой пакет контролов где это реализовано (например Telerik)
    Подсмотреть в их исходниках реализацию виртуализации и сделать свою в преферансом и дамами.
    Ответ написан
    Комментировать
  • Почему не отображается картинка в Image WPF?

    cyber_roach
    @cyber_roach
    UX дизайнер INEDIapps
    Гуглите WPF URI
    https://docs.microsoft.com/en-us/dotnet/framework/...

    А, да, .gif файл
    Для него лучше поискать компонент отображения. не умеет gif анимации проигрывать.
    Но в сети много примеров.
    Ответ написан
    2 комментария
  • Как добавить множество (больше тысячи) объектов к WrapPanel (WPF)?

    cyber_roach
    @cyber_roach
    UX дизайнер INEDIapps
    Во первых: не использовать wrappanel.
    Для подобной цели лучше canvas, но скорее всего более производительным будет написать свою панель компоновки. тут главное правило - как можно реже перерисовывать позиции элементов.
    https://docs.microsoft.com/ru-ru/dotnet/framework/...
    Далее сам объект, опять же наверняка вам не нужны все фичи класса Shapes, и судя по скрину все элементы одноразмерны. производительнее будет создать новый элемент основываясь на базовом frameworkelement с заданным набором свойств (цвет из enum и размер)
    Кстати элемент Border производительнее чем элемент Rectangle, не знаю с чем это связанно, но это вовсе не очевидно, основываясь на логике должно быть наоборот, но практика показывает иное. Попробуйте сами вывести N тысяч бордеров против Rectangle замерив производительность.

    Если элементы не всегда выводятся полностью на экран а со скроллом, то тут сразу виртуализация (отрисовывать только то что видимо).
    Далее добавление. элементов в панель.
    Советую просто хакнуть систему, добавляя не по одному, а срузу сотню-другую, или если количество элементов заранее известно - сразу сформировать их все (коллекцию прибиндить) на этапе загрузки. Просто сделать их невидимыми в цвет фона, далее просто меняя состояние нужного элемента на нужный цвет по индексу во время процесса (если таковой имеется) Работа с коллекциями производительнее чем всякие For c Children.Add.
    Скорее всего описанный мной вариант, значительно ускорит процесс, но пожрет уйму оперативной памяти и процессорного времени, тут решение только одно - растеризовать!
    Можно залить все элементы или же часть просто текстурой (например разбить на квадраты или полоски область карты)
    Алгоритм тут прост - рисуете элементы (лучше часть) - "фотографируете" - получившийся Image - вставляете на нужную область
    Вообще чистый хардкор это именно формировать квадраты не элементами а группой изображений.
    Это на несколько порядков снизит затраты на отрисовку, но писать такой код сможет не каждый, в особенности если квадраты не статичны (меняют состояние цвета) во время выполнения или требуется интерактив (тултип или клик по квадрату например), но всё возможно, мы даже растеризацией анимации делали, самое сложное это алгоритм корректный разработать.
    Самый простой, который приходит на ум - отрисовывать всю область как текстуру, на Canvas в нужное место выводить поверх 10-100 новых элементов, после чего рстеризовать всю область с новыми элементами в общую текстуру удалив эти элементы и рисуя новую партию. В итоге вообще получится просто image который ничего не весит и не ест процессор.
    Так же я бы поизучал исходные коды к примеру Telerik, у них много подобных контролов с выводом миллионов объектов. (например точки на графиках).
    Ответ написан
  • Почему wpf mousemove не срабатывает?

    cyber_roach
    @cyber_roach
    UX дизайнер INEDIapps
    Все верно, так и должно работать, это стандартное взаимодействие компонентов не только в WPF.
    После mousedown на кнопке мышь считается принадлежащей этому объекту, поэтому остальной UI на нее не реагирует.
    Конкретно для вашей задачи под drug-drop есть событие Drag Over - реакция на зажатую кнопку мыши тянущую объект drug над другим объектом (исключение из описанной выше ситуации). Обычно реакция делается, чтобы пользователь понимал куда можно "дропнуть" объект а куда нельзя, но ее можно использовать и в других кейсах.
    Ответ написан
    Комментировать
  • Как заставить заработать триггеры в ListViewItem?

    cyber_roach
    @cyber_roach
    UX дизайнер INEDIapps
    Потому что в DataTemplate вы создали еще один ListViewItem (вместо контента первого)
    В общем дереве объектов у вас получился ListViewItem вложенный в ListViewItem неудивительно что все сломалось.
    (DataTemplate создается для ContentPresenter в стиле)

    https://docs.microsoft.com/ru-ru/dotnet/api/system...
    Ответ написан
    1 комментарий
  • Как дебажить XAML?

    cyber_roach
    @cyber_roach
    UX дизайнер INEDIapps
    XAML - это язык разметки UI приложения. Не более. Там нет никакого исполнения кода, просто шаблон. Статика, Нельзя поставить точку останова.
    хотя XAML это тот же XML, а значит любой отладчик xml (если таковые существуют) применим.

    WPF подразумевает собой модель MVVM (XAML - слой View в MVVM)
    Если верно архитектуру проекта спроектировать то дебажить придется только ViewModel.

    А для облегчения жизни можно использовать Resharper или что-то подобное, облегчающее написание XAML кода.
    Ответ написан
    Комментировать
  • Как сделать чтобы фигура не вылазила за рамку при трансформациях?

    cyber_roach
    @cyber_roach
    UX дизайнер INEDIapps
    Или можно просто установить у бордера свойство обрезки контента
    https://docs.microsoft.com/ru-ru/dotnet/api/system...
    Ответ написан
    Комментировать
  • Как создавать свои контролы и анимации в UWP WPF?

    cyber_roach
    @cyber_roach
    UX дизайнер INEDIapps
    Фантазия и хардкор.
    Я не шучу, без фантазии и "hilevel математики + код + знание платформы" что-то кроме стандартных анимаций (вроде сдвига/поворота/прозрачности) сделать сложно будет.

    * Жалюзи можно сделать, например, используя маски прозрачности в WPF. (70% фантазии и 30% простого кода)
    * А можно написать код шейдера специально растеризующего изображение "жалюзями" (100% хардкодинга)
    вообще примеры с графическими шейдерами есть в сети.
    * Можно просто "хакнуть" систему сделав Path- фигуру которая будет жалюзями задав ей цвет фона и при достаточно быстрой анимации(используя чистый XAML) пользователю будет не заметен обман (100% фантазии)
    * Можно написать математически верный алгоритм на чистом C# используя несколько блоков Image в XAML показывающих часть изображения сдвинутого в определённых пропорциях в сумме составляющих анимацию жалюзи (50/50)
    * Посмотрите примеры от MS, у них на C# написаны всяческие летающие шарики и салютики для анимаций только кодом еще для древнего 3,5 фреймворка, код будет работать и под UWP
    Ответ написан
    Комментировать