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

Автоматическое рисование фигур на Canvas

21.04.2020, 14:54. Показов 3583. Ответов 22

Студворк — интернет-сервис помощи студентам
Здравствуйте дорогие софорумчане. Помогите решить проблему привязки данных. В моей проге необходимо реализовать привязку данных к Canvas. Существует класс PointArea
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
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
 
namespace MLP_Visualization.Points
{
 
    public class AreaPoint
    {
        //Название обасти
        public string title;
        //Коллекция точек в области
        public ObservableCollection<PointClass> Points  = new ObservableCollection<PointClass>();
        //Цвет точек области
        public ColorPoint Color { get; set; }
        //Центер области
        public Point center;
        //Радиус области
        public double r;
        //Колическво точек области
        public int countPoint;
        Gauss gauss = new Gauss();
 
        public AreaPoint(string title, Point center, double r, int countPoint, ColorPoint color)
        {
            this.title = title;
            this.center = center;
            this.r = r;
            this.countPoint = countPoint;
            this.Color = color;
            Generatepoint();
        }
 
        public AreaPoint()
        { 
        
        }
 
        public void Generatepoint()
        {
            for (int i = 0; i < Points.Count(); i++)
            {
                //Здесь генеририруются рандомно точки с нормальным распределением
                Points.Add(new PointClass(gauss.Next(center.X, center.Y, r)));
            }
        }
 
        public override string ToString()
        {
            string Property = title +"\r\n"+ "X= " + center.X + "Y= " + center.Y + "R= "+ r;
            return Property;
        }
 
        public bool Pressing(Point p)
        {
            if (Math.Pow((p.Y - center.Y), 2) + Math.Pow((p.X - center.X), 2) <= Math.Pow(r, 2))
                return true;
            else return false;
        }
 
        public void Move(Point p)
        { 
            
        }
    }
}
Мэйн класс
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
using System.Windows;
using System.Windows.Input;
using MLP_Visualization.Windows;
using MLP_Visualization.Points;
using System.Collections.ObjectModel;
 
namespace MLP_Visualization
{
    /// <summary>
    /// Логика взаимодействия для MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
       
        ObservableCollection<AreaPoint> ListArea;
 
 
        public MainWindow()
        {
            ObservableCollection<PointClass> points = new ObservableCollection<PointClass>
            {
                new PointClass(new Point(){ X = 100, Y = 100}),
                new PointClass(new Point(){ X=200,Y=200})
            };
            ListArea = new ObservableCollection<AreaPoint>()
            {
                new AreaPoint(){ Points = points}
            };
            InitializeComponent();
            DataContext = this;
           
        }
 
        private void AddClass_Click(object sender, RoutedEventArgs e)
        {
            AddPoint add = new AddPoint();
            add.ShowDialog();
            AreaPoint ap = add.GetArea;
            ListArea.Add(ap);
            ListPoint.Items.Add(ap.ToString());           
        }
 
    
        private void CanvasPoint_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
 
        }
 
        private void CanvasPoint_MouseMove(object sender, MouseEventArgs e)
        {
 
        }
    }
}
Мне необходимо привязать данные к Canvas так что бы когда я добавлял данные ListArea в ListArea добавились точки на Canvas. Проблема состоит в том что Points (коллекция точек) находится в коллекции ListArea и я не знаю как правильно организовать привязку данных. Пытался реализовать привязку вот таким образом:
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
<Window x:Class="MLP_Visualization.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:local="clr-namespace:MLP_Visualization"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid RenderTransformOrigin="0.6,0.489">
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition Width="200"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <ItemsControl ItemsSource="{Binding ListArea}" Grid.Column="1">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <Canvas x:Name="CanvasPoint"/>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Ellipse
                        InkCanvas.Top="{Binding Path=/Points/Top}"
                        InkCanvas.Left="{Binding Path=/Points/Left}"
                        Height="{Binding Path=/Points/PointR}"
                        Width="{Binding Path=/Points/PointR}"
                        Fill="Red"                   
                        StrokeThickness="2"
                        Stroke="Black"
                    />      
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
        <Button x:Name="AddClass" Content="Добавить класс" HorizontalAlignment="Left" Margin="73,55,0,0" VerticalAlignment="Top" Width="100" Click="AddClass_Click" Grid.Column="2"/>
        <ListView x:Name="ListPoint" Margin="0,100,0,100" Grid.Column="1" HorizontalAlignment="Left" Width="200"/>
    </Grid>
</Window>
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
21.04.2020, 14:54
Ответы с готовыми решениями:

Отрисовка сложных фигур на canvas
собственно вопрос, как из простых фигур, можно делать сложные? Когда я рисовал такие вот фигурки https://i.paste.pics/1PB0O.png все...

Рисование фигур
Всем доброго дня, у меня возник вопрос, можно ли через классы создать и вывести на форму в с # круг или эллипс?

Рисование фигур!
Всем привет! подскажите пожалуйста, как нарисовать несколько фигур в билдере, расположение которых будут меняться в зависимости от заданных...

22
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16165 / 11285 / 2892
Регистрация: 21.04.2018
Сообщений: 33,174
Записей в блоге: 2
12.05.2020, 00:01
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от фарафунг Посмотреть сообщение
возникает ошибка с перемещением классов.
Первая ошибка.
Перепутано в сеттерах всех свойств присвоение значения
Сделано так:
C#
35
36
37
38
39
        public double Y
        {
            get { return y; }
            set { value = y; .... }
        }
А надо:
C#
35
36
37
38
39
        public double Y
        {
            get { return y; }
            set { y = value; .... }
        }
Вторая ошибка.
Перепутано в вызове OnPropertyChanged имя поля с именем свойства - РЕГИСТР имеет значение!
Чтобы не было таких глупых ошибок метод надо объявлять так:
C#
1
2
3
4
        /// <summary>Метод для вызова события извещения об изменении свойства</summary>
        /// <param name="propertyName">Изменившееся свойство</param>
        public void OnPropertyChanged([CallerMemberName]string propertyName = "")
            => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
Тогда в свойстве его можно будет вызывать без имени
C#
35
36
37
38
39
        public double Y
        {
            get { return y; }
            set { y = value; OnPropertyChanged(); }
        }
Третья ошибка.
Так же для избежания путаницы поля хранящие значения свойств именуйте с нижнего слеша.
К этим полям можно обращаться ТОЛЬКО из сеттера и геттера одноимённого свойства.
Больше нигде в коде к ним обращения быть не должны. Без всяких вариантов!

И возьмите за базовую реализацию вот это класс Новая реализация OnPropertyChangedClass [WPF, Элд Хасп].
Тогда можете сделать от него наследование
C#
15
16
    public class PointClass : OnPropertyChangedClass, INotifyCollectionChanged
    {
А свойства можно будет объявлять так
C#
35
        public double Y { get => _y; set => SetProperty(ref _y, value); }
Четвёртое.
Не у всех свойств есть вызов OnPropertyChanged
C#
1
2
3
4
5
        public int PointR
        {
            get { return pointR; }
            set { value = pointR; }
        }
Пятая ошибка.
Ваш класс PointClass не реализует интерфейса IList и реализация в нём INotifyCollectionChanged - бессмыслена!
Это интерфейс для коллекций и он передаёт ИНДЕКСЫ изменившихся элементов.
А у вас в классе нет индексатора. Он просто не нужен.

Шестое.
Хранить значения свойств должны приватные ПОЛЯ, а не свойства
C#
1
2
3
        private Color colorPoint { get; set; }
 
        private string colorP { get; set; }
Седьмое.
Убрал ваш паразитический класс ColorPoint.

Восьмое.
Обращайте внимание на пространства имён используемых типов!
Вы используете System.Drawing.Color, а надо System.Windows.Media.Color !

Полностью код класса
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
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;
using System.Windows.Media;
 
namespace MLP_Visualization.Points
{
    public class PointClass : OnPropertyChangedClass
    {
 
        private int _pointR = 10;
        private double _x;
        private double _y;
        private double _top;
        private double _left;
        private Color _colorPoint;
 
        public static ObservableCollection<PointClass> ListPoint { get; set; } = new ObservableCollection<PointClass>();
 
        public double X { get => _x; set => SetProperty(ref _x, value); }
        public double Y { get => _y; set => SetProperty(ref _y, value); }
 
        public double Top { get => _top; set => SetProperty(ref _top, value); }
 
        public int PointR { get => _pointR; set => SetProperty(ref _pointR, value); }
 
        public Color ColorPoint { get => _colorPoint; set => SetProperty(ref _colorPoint, value); }
 
        public double Left { get => _left; set => SetProperty(ref _left, value); }
 
        public PointClass(Point p, Color color)
        {
            X = p.X;
            Y = p.Y;
            Top = p.Y - PointR;
            Left = p.X - PointR;
            ColorPoint = color;
            Add(this);
        }
 
        public PointClass()
        {
 
        }
 
        public void Add(PointClass p)
        {
            ListPoint.Add(p);
        }
 
        public void Update(PointClass p, double x, double y)
        {
            int index = -1;
            for (int i = 0; i < ListPoint.Count(); i++)
            {
                if (p == ListPoint[i])
                {
                    index = i; break;
                }
            }
            ListPoint[index].X += x;
            ListPoint[index].Y += y;
            ListPoint[index].Top = Y - PointR;
            ListPoint[index].Left = X - PointR;
        }
 
        public void Remove(PointClass point)
        {
            int index = 0;
            for (int i = 0; i < ListPoint.Count; i++)
            {
                if (ListPoint[i] == point)
                {
                    index = i; break;
                }
            }
            ListPoint.RemoveAt(index);
        }
 
    }
}
Проверьте.
Какие будут проблемы - отпишите.

Но сам класс выглядит, мягко говоря, по идиотски.
Тип и коллекция с этим типом должны быть РАЗНЫМИ классами.
А у вас здесь и создание экземпляра класса и методы для работы с коллекцией.
Каша конкретная и широкая дорога к различным багам.
0
1 / 0 / 1
Регистрация: 20.12.2016
Сообщений: 13
13.05.2020, 12:45  [ТС]
Спасибо за помощь. Теперь ошибка возникла с xaml. Я привязываю событие MouseDown, MouseMove и MouseUp к Canvas, но почему-то эти события работают только для точек что отрисовываются, а на нажатие на холст вообще не реагируют.
Вложения
Тип файла: rar MLP_Visualization.rar (278.6 Кб, 2 просмотров)
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16165 / 11285 / 2892
Регистрация: 21.04.2018
Сообщений: 33,174
Записей в блоге: 2
14.05.2020, 11:49
Цитата Сообщение от фарафунг Посмотреть сообщение
Я привязываю событие MouseDown, MouseMove и MouseUp к Canvas, но почему-то эти события работают только для точек что отрисовываются, а на нажатие на холст вообще не реагируют.
Потому, что точки рисуются в панели ItemsControl.
Внешний Canvas просто не нужен.

И надо задавать кисть фона.
Если её нет (null) - это означает что фон прозрачен для кликов.

Правильная разметка
XML
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
    <Grid RenderTransformOrigin="0.6,0.489">
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition Width="200"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition/>
        </Grid.RowDefinitions>
            <ItemsControl ItemsSource="{Binding Source={x:Static p:PointClass.ListPoint}}">
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <Canvas  MouseDown="Mouse_CanvasDown" MouseMove="Mouse_CanvasMove" MouseUp="Mouse_CanvasUp" 
                                 Background="Transparent"/>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
                <ItemsControl.ItemTemplate>
                    <DataTemplate DataType="{x:Type p:PointClass}">
                        <Ellipse
                            Height= "{Binding PointR}"
                            Width= "{Binding PointR}"                                       
                            StrokeThickness="1"
                            Stroke="Black"
                    >
                            <Ellipse.Fill>
                                <SolidColorBrush Color="{Binding ColorPoint}"/>
                            </Ellipse.Fill>
                        </Ellipse>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
                <ItemsControl.ItemContainerStyle>
                    <Style TargetType="{x:Type ContentPresenter}">
                        <Setter Property="Canvas.Top" Value="{Binding Top}"/>
                        <Setter Property="Canvas.Left" Value="{Binding Left}"/>
                    </Style>
                </ItemsControl.ItemContainerStyle>
            </ItemsControl>
        <Button x:Name="AddClass" Content="Добавить класс" HorizontalAlignment="Left" Margin="73,55,0,0" VerticalAlignment="Top" Width="100" Click="AddClass_Click" Grid.Column="2"/>
        <ListView x:Name="ListPoint" Margin="0,100,0,100" Grid.Column="1" HorizontalAlignment="Left" Width="200"/>
    </Grid>
</Window>
Но в такой разметке возникнут ошибки в CB Окна, так как вы нарушили одно из правил MVVM - View не должна работать с данными!

Поэтому ещё раз пишу вам.
У вас очень запутанный проект.
Фактически просто свалка кода.
ДО создания WPF представления вам нужно сначала правильно создать саму архитектуру, иерархию данных в Model.
И предоставить к ней доступ через VM.
Если будете делать правильно - реализация вашей задачи это полдня от силы.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
14.05.2020, 11:49

Рисование фигур
написать программу которая спрашивает у пользователя какую фигуру надо нарисовать: 1 - прямоугольник, 2 - круг, 3 - дугу и какого цвета;и...

Рисование фигур
Описать базовый класс Фигура, который имеет один виртуальный метод void Draw (Graphics g). Описать 3 класса наследники Окружность,...

Рисование фигур
Разобрался как нарисовать фигу, но как сделать когда зажал кнопку мыши то появляется контур этой фигуры??? а как отпустил нарисовалась сама...

Рисование фигур
Программа вывода прямоугольного треугольника заполненного звездочками с вершиной N с использование цыклов while

Рисование фигур
Сделал пример с книги, должен по идее рисоваться круг и результат быть такой, как в книге: Рисуем круг: (0, 0, 100) Прошло...


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

Или воспользуйтесь поиском по форуму:
23
Ответ Создать тему
Новые блоги и статьи
Архитектура биовида Стива в Майнкрафте: Зачем бонобо кубический каннибализм
anaschu 30.08.2026
Кубический Вагинокапитализм в Minecraft: Математический инвариант ОДУ и рок Стивов-бонобо Главная задача разработанной «Модели Всего» — наглядно продемонстрировать наличие системной «судьбы». . .
Оттачиваю умение писать js программы.
russiannick 30.08.2026
Проектом выходного дня стало написание Книги шифров Виженера. Итогом стала версия 200, синий туман. Синий туман назван так, потому что замораживает текст под собой. Нажатие синих кнопок управляют. . .
мат медиц модель 30. презентация проекта
anaschu 27.08.2026
хоп хоп хоп хидахоп, а я кладую))
Как у меня протекала болезнь
zorxor 27.08.2026
Здравствуйте, друзья! Эта запись блога предназначена именно для вас - для моих дорогих друзей, которые знали меня лично. Чтобы ответить на вопрос - а что же со мной произошло на самом деле? Я учился. . .
Нашел вот забавное видео о измерениях. Лучшее что я видел на эту тему
kumehtar 26.08.2026
ILETXiw9bMQ Основная суть и тезисы по измерениям: 0D (Нулевое измерение): точка, не имеющая длины, ширины, высоты или объема. Объект не может перемещаться в 0D. 1D (Первое измерение):. . .
[EasyBuilder Pro] Памятка по разработке для панелей Weintek
ФедосеевПавел 26.08.2026
Памятка по разработке для панелей Weintek ВВЕДЕНИЕ Ранее, при реализации проектов основное внимание уделял разработке управляющей программы для контроллера, а панели оператора доставалось время. . .
Модель по догадкам
anaschu 25.08.2026
Прошло две недели. Я уже рассказывал, как разговаривал с сотрудниками у сортировки и как понял, что главная ветка — не про приёмку, а про отбор. Но тогда я думал, что понял механику. На этой неделе я. . .
Запись в регистр сведений независимо от заполненности табличной части
Maks 25.08.2026
Реализация из решения ниже выполнена на нетиповом документе с несколькими табличными частями, разработанного в КА2. Задача: Обеспечить запись документа в регистр сведений независимо от. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru