Форум программистов, компьютерный форум, киберфорум
C#: WPF, UWP и Silverlight
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 Аватар для Midian
605 / 387 / 198
Регистрация: 31.03.2013
Сообщений: 2,687

Контрол для задания угла поворота

14.03.2025, 09:01. Показов 1583. Ответов 12
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
День добрый, хочу сделать свой кастомный контрол, который показывал бы угол поворота в градусах, так вот, сам контрол простой и сделан, а вот логику расчета поворота относительно оси не знаю как посчитать, мб кто-то подскажет и делал уже подобное. Вот разметка:
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
<Window x:Class="WpfApp3.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:i="http://schemas.microsoft.com/xaml/behaviors"
        xmlns:local="clr-namespace:WpfApp3"
        mc:Ignorable="d"
        d:DataContext="{d:DesignInstance local:MainViewModel}"
        Title="MainWindow" Height="450" Width="800">
    <Window.DataContext>
        <local:MainViewModel />
    </Window.DataContext>
    <Grid>
        <Grid Width="150" Height="150" Background="Transparent">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="MouseMove">
                    <i:InvokeCommandAction Command="{Binding MouseMoveCommand}" PassEventArgsToCommand="True" />
                </i:EventTrigger>
            </i:Interaction.Triggers>
 
            <Grid RenderTransformOrigin="0.5,0.5">
                <Grid.RenderTransform>
                    <RotateTransform Angle="{Binding Angle}"/>
                </Grid.RenderTransform>
 
                <Border CornerRadius="50" Width="100" Height="100" BorderBrush="Gray" BorderThickness="2"
                        RenderTransformOrigin="0.5,0.5"/>
                <Border Margin="0,0,96,0" Width="10" Height="10" CornerRadius="10" Background="#276FF6"/>
            </Grid>
            <TextBlock Margin="5,0,0,0" Text="{Binding Angle, StringFormat='{}{0}°'}" FontWeight="Bold" VerticalAlignment="Center" HorizontalAlignment="Center"/>
        </Grid>
    </Grid>
</Window>
А вот VM:
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
public class MainViewModel : ObservableObject
{
    public MainViewModel()
    {
        MouseMoveCommand = new RelayCommand<MouseEventArgs>(OnMouseMove);
    }
 
    private double _angle;
    public double Angle
    {
        get => _angle;
        set => SetProperty(ref _angle, value);
    }
 
    public IRelayCommand<MouseEventArgs> MouseMoveCommand { get; }
    private void OnMouseMove(MouseEventArgs args)
    {
        if (args.LeftButton == MouseButtonState.Pressed)
        {
            var point = args.GetPosition(null);
            Angle = Math.Round(Math.Asin(point.Y / point.X), 0);
        }
    }
}
Выглядит это следующим образом:
Изображения
 
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
14.03.2025, 09:01
Ответы с готовыми решениями:

Определение угла поворота изображения
Всем привет! Столкнулся с следующей проблемой: имеется сканированное изображение (после бинаризованное), на котором имеется таблица....

Контроль угла поворота цилиндра
Добрый день! Есть цилиндр который вращается, я через камеру с помощью EMGU(openCV) беру два соседних кадра и определяю контрольный точки...

Поворот контрола кодом
Как в коде повернуть существующий контрол?

12
 Аватар для Midian
605 / 387 / 198
Регистрация: 31.03.2013
Сообщений: 2,687
14.03.2025, 09:03  [ТС]
Хочу чтобы когда пользователь зажал ЛКМ и потянув в одну из сторон синий шарик вращался относительно оси и показывал угол отклонения, подскажите как такое реализовать можно
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16115 / 11236 / 2887
Регистрация: 21.04.2018
Сообщений: 33,037
Записей в блоге: 2
14.03.2025, 10:00
Цитата Сообщение от Midian Посмотреть сообщение
потянув в одну из сторон
Не совсем понял.

За "что" потянув?
0
 Аватар для Midian
605 / 387 / 198
Регистрация: 31.03.2013
Сообщений: 2,687
14.03.2025, 10:03  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
За "что" потянув?
Зажали ЛКМ и потянули просто в сторону, сработал event MouseMove и вот там нужно рассчитать угол поворота и передать его в проперти Angle, другими словами, синий шарик должен следовать за мышью, но только по оси
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16115 / 11236 / 2887
Регистрация: 21.04.2018
Сообщений: 33,037
Записей в блоге: 2
14.03.2025, 11:26
Цитата Сообщение от Midian Посмотреть сообщение
Зажали ЛКМ и потянули просто в сторону
Зажали и удерживаем "синий кружок (точку)"?

Если да, то вам тут не команда нужна.

Примерный алгоритм:
1) При ЛКМ захватываете мышь "синей точкой" - Mouse.Capture ;
2) После захвата подключаете отслеживание положения курсора;
3) При изменении положения рассчитываете координату курсора относительно центра окружности - Mouse.GetPosition(Центр окружности);
4) По координате курсора рассчитать угол - Math.Atan2(Double, Double);
5) Полученный угол передать в VM через метод или команду.

Добавлено через 13 минут
Цитата Сообщение от Midian Посмотреть сообщение
Math.Asin(point.Y / point.X)
Нужна другая функция: Math.Atan2(Double, Double)
0
 Аватар для Midian
605 / 387 / 198
Регистрация: 31.03.2013
Сообщений: 2,687
14.03.2025, 11:42  [ТС]
В общем, обратился к дик пику
И за минут 5 мы с ним добились желанного результата, если кому-то понадобится, рабочий код тут:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public IRelayCommand<MouseEventArgs> MouseMoveCommand { get; }
private void OnMouseMove(MouseEventArgs args)
{
    if (args.LeftButton == MouseButtonState.Pressed && args.Source is Grid grid)
    {
        var mousePoint = args.GetPosition(grid);
 
        var centerX = grid.ActualWidth / 2;
        var centerY = grid.ActualHeight / 2;
 
        var deltaX = centerX - mousePoint.X;
        var deltaY = centerY - mousePoint.Y;
 
        var angleInRadians = Math.Atan2(deltaY, deltaX);
 
        var angleInDegrees = angleInRadians * (180 / Math.PI);
 
        Angle = Math.Round(angleInDegrees, 0);
    }
}
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16115 / 11236 / 2887
Регистрация: 21.04.2018
Сообщений: 33,037
Записей в блоге: 2
14.03.2025, 11:51
Цитата Сообщение от Midian Посмотреть сообщение
рабочий код тут:
Токо этот код явно не для VM.
В VM нужно передавать только значение угла.

Добавлено через 2 минуты
Цитата Сообщение от Midian Посмотреть сообщение
обратился к дик пику
Я его в основном для сложных регулярок использую.
Самому, как-то всё не хватает времени их поглубже изучить.
0
 Аватар для Midian
605 / 387 / 198
Регистрация: 31.03.2013
Сообщений: 2,687
14.03.2025, 11:52  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Токо этот код явно не для VM.
это почему? то что я там выдергиваю Grid и забираю его ширину/высоту не вижу ничего криминального по хорошему можно спрятать его тогда за Interface с нужными мне свойствами, но это все такое
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16115 / 11236 / 2887
Регистрация: 21.04.2018
Сообщений: 33,037
Записей в блоге: 2
14.03.2025, 15:54
Цитата Сообщение от Midian Посмотреть сообщение
то что я там выдергиваю Grid и забираю его ширину/высоту не вижу ничего криминального
Это прямое нарушение MVVM.
И прятать за интерфейсом его тоже не надо.
Эта логика View, а не ViewModel.

Перемешает пользователь точку курсор, или кнопками клавиатуры, или просто задаёт новые координаты или новый угол - для ViewModel это не важно. VM нужно только получить новый угол. А откуда он взялся VM волновать не должно.

Добавлено через 2 минуты
Достаточно переместить обработчик в Code Behind и там передавать в VM:

C#
18
        ((MainViewModel)grid.DataContext).Angle = Math.Round(angleInDegrees, 0);
Добавлено через 49 секунд
Если хочется без Code Behind, то вместо вызова команды в событии надо прописать Behavior.
0
 Аватар для Midian
605 / 387 / 198
Регистрация: 31.03.2013
Сообщений: 2,687
14.03.2025, 19:09  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Это прямое нарушение MVVM.
не соглашусь
Цитата Сообщение от Элд Хасп Посмотреть сообщение
И прятать за интерфейсом его тоже не надо.
таким образом не будет нарушен mvvm, будет приводиться к IGrid интерфейсу например у которого будет только 2 свойства которые мне нужны и не более
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Эта логика View, а не ViewModel.
у View вообще никакой логики не должно быть, на то она и View, разметка и максимум триггеры и анимации
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Достаточно переместить обработчик в Code Behind и там передавать в VM:
Code Behind - это зло и такое советовать я бы не стал никому
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Если хочется без Code Behind, то вместо вызова команды в событии надо прописать Behavior.
плодить behavior ради 2 свойств, вы серьезно?
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16115 / 11236 / 2887
Регистрация: 21.04.2018
Сообщений: 33,037
Записей в блоге: 2
14.03.2025, 19:36
Цитата Сообщение от Midian Посмотреть сообщение
не соглашусь
???
А причём здесь ваше согласие?
Есть требования паттерна вы или соблюдаете их или нет.

Цитата Сообщение от Midian Посмотреть сообщение
таким образом не будет нарушен mvvm,
Не будет нарушено одно из требований "Слабая зависимость между слоя".
Но нарушает требования по логическому функционалу.

Цитата Сообщение от Midian Посмотреть сообщение
у View вообще никакой логики не должно быть, на то она и View, разметка и максимум триггеры и анимации
Чаво???!!!
Это вы откуда взяли?

В View может сдержаться огромная логика.
И никакая XAML разметка не заменит Шарпа (или другого полноценного ЯП).

Не путайте Code Behind с любым кодом Шарпа.
Но даже Code Behind не нарушает MVVM.

Цитата Сообщение от Midian Посмотреть сообщение
плодить behavior ради 2 свойств, вы серьезно?
А почему нет?
Но это альтернатива Code Behind.
Если приложение делается "в одного", не требований по тестированию, по поддержке и т.п., то вполне можно использовать и Code Behind.

Добавлено через 2 минуты
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Но нарушает требования по логическому функционалу.
Ещё раз задумайтесь, как ваша View будет работать с консольным представлением?
Зачем в консоле IGrid ?

ViewModel - это не замена Code Behind для View. Это оболочка для Model, которая делает удобным использование Модели в Представлении.

Добавлено через 3 минуты
Или другой пример.

Вам приспичило заменить Grid на Canvas или на кастомный UIElement, который не предоставляет ActualWidth/Height/
И теперь из-за хотелки дизайнера UI надо вносить изменения в ViewModel?
То есть формально IGrid вроде позволяет реализовать слабую зависимость, но логически эта зависимость всё равно остаётся сильной.
0
 Аватар для Midian
605 / 387 / 198
Регистрация: 31.03.2013
Сообщений: 2,687
17.03.2025, 09:31  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Ещё раз задумайтесь, как ваша View будет работать с консольным представлением?
А как ваш behavior будет работать?
Цитата Сообщение от Элд Хасп Посмотреть сообщение
ViewModel - это не замена Code Behind для View.
вот именно, что это замена, VM - это разделение слоев и этот слой потом удобно покрывать тестами
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Вам приспичило заменить Grid на Canvas или на кастомный UIElement, который не предоставляет ActualWidth/Height/
И теперь из-за хотелки дизайнера UI надо вносить изменения в ViewModel?
То есть формально IGrid вроде позволяет реализовать слабую зависимость, но логически эта зависимость всё равно остаётся сильной.
У канваса разве нету Width/Height?
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16115 / 11236 / 2887
Регистрация: 21.04.2018
Сообщений: 33,037
Записей в блоге: 2
17.03.2025, 10:53
Цитата Сообщение от Midian Посмотреть сообщение
А как ваш behavior будет работать?
Любым доступным в View способом получать от действий пользователя требуемый угол и передавать его в ViewModel уже как готовая величина.

Цитата Сообщение от Midian Посмотреть сообщение
вот именно, что это замена, VM - это разделение слоев и этот слой потом удобно покрывать тестами
Не путайте слои и Code Behind.

Слой VM - он работает с данными Модели. По сути это просто какая-то оболочка над Моделью, которая позволяет View удобно работать с Моделью.

Code Behind - согласен, что ухудшает модульность, тестирование и т.п.
В основном используется "для быстрого тестирования" работоспособности каких-то вариантов реализации.
Но Шарп в View это не только Code Behind. Это (из того что сразу в голову пришло) конвертеры, расширения разметки, Behavoir, триггера, различные прокси, вспомогательные типы и контейнеры (в том числе локаторы, навигаторы, мессенджеры и т.д.), Custom Control, Attached Property. И всё это прекрасно и удобно тестируется, поддерживается, модернизируется.

Цитата Сообщение от Midian Посмотреть сообщение
У канваса разве нету Width/Height?
Центр Canvas может не совпадать с центром дочерних элементов - в канвас не работают Horizontal/VerticalAlignment.
Так же Canvas не выравнивает свой размер по дочерним, а дочерние по размеру Canvas.

Один из типичных примеров использования канвас - это создание Canvas с нулевыми размерами и использование его в центре координатной плоскости. В таком случае Canvas.Top/Left автоматически становятся координатами.
А нулевые размеры Canvas никак не мешают выводу дочерних элементов.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
17.03.2025, 10:53
Помогаю со студенческими работами здесь

поворот контрола
собственно как программно повернуть контрол (желательно label, textbox или richtextbox) на 90 градусов?

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

Поворот фигуры: Как перевести значение угла в число? Что тут неправильно?
На вход подается значение угла допустим 30 градусов нужно его преобразовать в число. Как это сделать?

Расчет углов. Задание манипулятор
Доброго времени суток. Это моя 1 тема на форуме поэтому не судите строго. Учу c# самостоятельно и не долго. Прохожу задания вот на этом...

Задание стиля по умолчанию для нового контрола
Здравствуйте. Подскажите, как создать стиль «по умолчанию» для наследника, например кнопки? Если учитывать, что наследник находиться в...


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

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru