Я пытаюсь создать приложение WPF, в котором у меня есть список элементов (в данном случае стен) в DataGrid, и я хочу визуализировать геометрию элементов (стен). Я прикрепил изображение ниже.
По сути, мои элементы — это стены, имеющие высоту и длину. Стены должны быть наложены друг на друга, как на изображении ниже. (При инициализации они аккуратно сложены друг на друга только потому, что я вручную инициализировал свой список именно так.)
MainWindow
Главное окно, которое вы видите выше состоит из трех столбцов:
0 — в левом столбце есть панель стека, содержащая DataGrid.
1 — в среднем столбце есть ItemsControl. , при этом для ItemsPanelTemplate установлено значение холста. Большой красный квадрат показывает контур холста в качестве временного ориентира.
2 – Правый столбец пока неактуален/не используется.
В приведенном ниже коде показано, как настраивается ItemsControl/Canvas. По сути, я визуализирую стены как границы с определенным размером и положением в зависимости от введенных данных. Я мог бы использовать и прямоугольники, но не нашел существенных плюсов/минусов.
Вот изображение моего обозревателя решений для краткого обзора:
Обозреватель решений
Стены определяются этим классом:
По сути, высота и длина — это размеры стены в реальной жизни. Я использую шкалу 50, чтобы получить XLength и YHeight, то есть размер границы, обозначающей каждую стену. Аналогично, каждая стена имеет XPos и YPos с одинаковым масштабом, который определяет ее положение на холсте.
public class Wall : INotifyPropertyChanged
{
private static int _scale = 50;
private string _floor; //Just a string of text displayed on each Border
private double _height; //Height of wall IRL
private double _length; //Lenght of wall IRL
private double _xPos; //Horizonal position on canvas (Canvas.Left)
private double _yPos; //Vertical position on canvas (Canvas.Top)
private double _xLength; //Width of Border on canvas (IRL Length * Scale)
private double _yHeight; //Height of Border on canvas (IRL Height * Scale)
public string Floor
{
get { return _floor; }
set { _floor = value; }
}
public double Height
{
get { return _height; }
set
{
_height = value;
_yHeight = value*_scale;
OnPropertyChanged("YHeight");
}
}
public double Length
{
get { return _length; }
set
{
_length = value;
_xLength = value*_scale;
OnPropertyChanged("XLength");
}
}
public double XPos
{
get { return _xPos; }
set { _xPos = value; }
}
public double YPos
{
get { return _yPos; }
set { _yPos = value; }
}
public double XLength
{
get { return _xLength; }
set { _xLength = Length * _scale; }
}
public double YHeight
{
get { return _yHeight; }
set { _yHeight = Height * _scale; }
}
public event PropertyChangedEventHandler? PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string name = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
Переменные стены описаны на этом рисунке:
Описание XLength, YHeight, XPos, YPos
В свойствах XLength и YHeight я успешно применил несколько простых формул, чтобы длина и высота соответствовали друг другу. Например, когда я меняю несколько значений в DataGrid, я могу получить что-то вроде этого:
MainWindow, когда значения в DataGrid изменились
Однако , я хотел бы изменить свойство YPos, чтобы стены всегда располагались друг над другом. Итак, если я изменю высоту четвертого этажа, все стены ниже него должны изменить свое значение YPos и так далее. Мне это не удалось, и я прошу вашей помощи!
Я пытался создать метод, который делает что-то вроде этого:
public void OrderWalls()
{
for (int i = 0; i < _walls.Count; i++)
{
Walls.YPos = Walls[i-1].YPos + Walls.YHeight;
}
}
Но я не могу понять, как применить этот метод в свойстве YPos. Или я все делаю неправильно? Любая помощь приветствуется!
Вот моя ViewModel и код моего главного окна:
public class MainWindowViewModel : INotifyPropertyChanged
{
private ObservableCollection _walls;
public ObservableCollection Walls
{
get { return _walls; }
set
{
_walls = value;
OnPropertyChanged();
}
}
public void OrderWalls()
{
for (int i = 0; i < _walls.Count; i++)
{
Walls.YPos = Walls[i-1].YPos + Walls.YHeight;
}
}
public MainWindowViewModel()
{
Walls = new ObservableCollection();
Walls.Add(new Wall { Floor = "Floor 4", Height = 3, Length = 6, YPos = 50, XPos = 50 });
Walls.Add(new Wall { Floor = "Floor 3", Height = 3, Length = 6, YPos = 200, XPos = 50 });
Walls.Add(new Wall { Floor = "Floor 2", Height = 3, Length = 6, YPos = 350, XPos = 50 });
Walls.Add(new Wall { Floor = "Floor 1", Height = 3, Length = 6, YPos = 500, XPos = 50 });
}
public event PropertyChangedEventHandler? PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string name = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
public partial class MainWindow : Window
{
public MainWindow()
{
MainWindowViewModel viewModel = new MainWindowViewModel();
this.DataContext = viewModel;
InitializeComponent();
}
}
Подробнее здесь: https://stackoverflow.com/questions/787 ... changing-a