Загрузка данных


using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using Microsoft.Win32;
using Xbim.Ifc;
using Xbim.Ifc4.Interfaces;

namespace IfcBimEditor
{
    public partial class MainWindow : Window
    {
        private IfcStore _model;
        private string _openedPath;
        private List<IIfcObject> _selected = new List<IIfcObject>();
        private Dictionary<string, IfcTreeNode> _nodes = new Dictionary<string, IfcTreeNode>();

        public MainWindow() { InitializeComponent(); }

        private List<IIfcObject> Selected => _selected;

        private void Open_Click(object sender, RoutedEventArgs e)
        {
            var dialog = new OpenFileDialog { Filter = "IFC (*.ifc)|*.ifc" };
            if (dialog.ShowDialog() != true) return;
            try
            {
                Viewer.Model = null;
                _model?.Dispose();
                _model = IfcStore.Open(dialog.FileName);
                _openedPath = dialog.FileName;
                // Создание геометрии для отображения.
                var context = new Xbim.ModelGeometry.Scene.Xbim3DModelContext(_model);
                context.CreateContext();
                Viewer.Model = _model;
                Viewer.ReloadModel();
                BuildIfcTree();
                StatusText.Text = $"Открыт: {_openedPath}";
            }
            catch (Exception ex) { MessageBox.Show(ex.Message, "Ошибка открытия"); }
        }

        private void BuildIfcTree()
        {
            _selected.Clear();
            _nodes.Clear();
            var objects = _model.Instances.OfType<IIfcObject>().ToList();
            var groups = objects.GroupBy(o => o.ExpressType.Name)
                .OrderBy(g => g.Key)
                .Select(g => new IfcTreeNode
                {
                    Type = g.Key + " (" + g.Count() + ")",
                    Children = new System.Collections.ObjectModel.ObservableCollection<IfcTreeNode>(
                        g.OrderBy(o => o.Name.ToString()).Select(o =>
                        {
                            var node = new IfcTreeNode
                            {
                                Type = o.ExpressType.Name,
                                Name = o.Name.ToString(),
                                Description = o.Description.ToString(),
                                Element = o
                            };
                            _nodes[o.GlobalId.ToString()] = node;
                            return node;
                        }))
                }).ToList();
            IfcTree.ItemsSource = groups;
            UpdateProperties();
        }

        private void IfcTree_SelectedItemChanged(object sender,
            RoutedPropertyChangedEventArgs<object> e)
        {
            var node = e.NewValue as IfcTreeNode;
            if (node?.Element == null) return;
            _selected = new List<IIfcObject> { node.Element };
            UpdateProperties();
        }

        private void UpdateProperties()
        {
            var selected = Selected;
            SelectedCount.Text = $"Выбрано: {selected.Count}";
            var item = selected.FirstOrDefault();
            if (item == null) { PropertiesGrid.ItemsSource = null; return; }
            var rows = new List<PropertyRow>
            {
                new PropertyRow { Group = "IFC", Name = "Class", Value = item.ExpressType.Name },
                new PropertyRow { Group = "IFC", Name = "GlobalId", Value = item.GlobalId.ToString() },
                new PropertyRow { Group = "IFC", Name = "Name", Value = item.Name.ToString() },
                new PropertyRow { Group = "IFC", Name = "Description", Value = item.Description.ToString() }
            };
            foreach (var rel in item.IsDefinedBy.OfType<IIfcRelDefinesByProperties>())
                if (rel.RelatingPropertyDefinition is IIfcPropertySet ps)
                    foreach (var prop in ps.HasProperties.OfType<IIfcPropertySingleValue>())
                        rows.Add(new PropertyRow { Group = ps.Name.ToString(),
                            Name = prop.Name.ToString(), Value = prop.NominalValue?.ToString() });
            PropertiesGrid.ItemsSource = rows;
        }

        private void Similar_Click(object sender, RoutedEventArgs e)
        {
            if (_model == null || Selected.Count == 0) return;
            _selected = IfcEditor.FindSimilar(_model, Selected[0], MatchMode.SelectedIndex);
            UpdateProperties();
            StatusText.Text = $"Найдено подобных элементов: {_selected.Count}. Группа готова к редактированию.";
        }

        private void Apply_Click(object sender, RoutedEventArgs e)
        {
            if (_model == null || Selected.Count == 0) { MessageBox.Show("Выберите элементы."); return; }
            var pset = PsetInput.Text.Trim();
            var prop = PropertyInput.Text.Trim();
            if (pset.Length == 0 || prop.Length == 0) { MessageBox.Show("Укажите Pset и имя свойства."); return; }
            if (MessageBox.Show($"Изменить {prop} у {Selected.Count} элементов?",
                "Подтверждение", MessageBoxButton.YesNo) != MessageBoxResult.Yes) return;
            try
            {
                var count = IfcEditor.SetStringProperty(_model, Selected, pset, prop,
                    ValueInput.Text, CreateMissing.IsChecked == true);
                StatusText.Text = $"Изменено элементов: {count}. Сохраните IFC.";
                UpdateProperties();
            }
            catch (Exception ex) { MessageBox.Show(ex.Message, "Ошибка изменения"); }
        }

        private void Save_Click(object sender, RoutedEventArgs e)
        {
            if (_model == null) return;
            var dialog = new SaveFileDialog { Filter = "IFC (*.ifc)|*.ifc",
                FileName = System.IO.Path.GetFileNameWithoutExtension(_openedPath) + "_edited.ifc" };
            if (dialog.ShowDialog() != true) return;
            if (string.Equals(dialog.FileName, _openedPath, StringComparison.OrdinalIgnoreCase))
            { MessageBox.Show("Выберите новое имя файла для сохранения."); return; }
            try { _model.SaveAs(dialog.FileName); StatusText.Text = "Сохранено: " + dialog.FileName; }
            catch (Exception ex) { MessageBox.Show(ex.Message, "Ошибка сохранения"); }
        }

        protected override void OnClosed(EventArgs e) { _model?.Dispose(); base.OnClosed(e); }
        public sealed class PropertyRow { public string Group { get; set; } public string Name { get; set; } public string Value { get; set; } }
    }
}
namespace IfcBimEditor
{
    public sealed class IfcTreeNode
    {
        public string Type { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
        public Xbim.Ifc4.Interfaces.IIfcObject Element { get; set; }
        public System.Collections.ObjectModel.ObservableCollection<IfcTreeNode> Children { get; set; }
            = new System.Collections.ObjectModel.ObservableCollection<IfcTreeNode>();
    }
}