C# Problems with dependent datagrids, Binding and ICollectionView

101 views Asked by At

I have the following challenge and hope that you can help me:

  1. files shall be displayed in a datagrid -> works

  2. if a file is selected in the datagrid, a description should be displayed in a textbox and the user should be allowed to change it -> works

  3. furthermore, the corresponding manufacturers should be listed in a second DataGrid, depending on which file was selected. By selecting a manufacture, all associated CategoryA and CategoryB should be displayed in a third datagrid. -> does not work

  4. in a fourth DataGrid, depending on what was selected in the third Datagrid, the associated properties should be displayed. -> does not work

  5. the data should be saved, if necessary read in again -> works

The points 3. and 4. cause me headaches. On the one hand because the binding does not work and on the other hand my ICollectionView does not work as I want, because at the moment all Datagrids are controlled in the same way. Here I would like to have dependencies, the respective Datagrid is to indicate thus always only information of that, which was selected in the previous Datagrid.

I hope you can follow me and give me some examples or sources to help me.

Enclosed are my code attempts:

//MainWindow.xaml.cs
using System.IO;
using System.Windows;
using System.Windows.Data;
using System.ComponentModel;
using XXX.Model;
using System.Xml.Serialization;
using System.IO.Compression;

namespace XXX
{
 public partial class MainWindow : Window
    {
        private FileCollection _fileList;
        private ICollectionView _fileListCollectionView;
        private FileInfo _fileListFile;
        
        public MainWindow()
        {
            InitializeComponent();

            _fileListCollectionView = new ListCollectionView(new FileCollection());
            OpenSettings(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location) + @"\UserSettings");
            
            SetView(new FileCollection());
            _fileList.Add(new Model.File {FolderPath = @"\FolderPath\Example1", FileName = "File1", Description = "Text from file 1 which may be changed later by the user" });
            _fileList.Add(new Model.File { FolderPath = @"\FolderPath\Example2", FileName = "File2", Description = "Text from file 2 which may be changed later by the user" });
            _fileList.Add(new Model.File { FolderPath = @"\FolderPath\Example3", FileName = "File3", Description = "Text from file 3 which may be changed later by the user" });
            //........
            //........
            if (_fileList != null)
            {
                foreach (var file in _fileList)
                {
                    string filePath = System.IO.Path.Combine(file.FolderPath, file.FileName);
                    if (System.IO.File.Exists(filePath))
                    {
                        file.Manufacturer.Add(new Manufacturer() { Name = "First manufacturer" });
                        file.Manufacturer[file.Manufacturer.Count - 1].CategorysA.Add(new CategoryA() { PropertyA1 = "PropA1",PropertyA2= "PropA2", PropertyA3 ="PropA3" });
                        file.Manufacturer[file.Manufacturer.Count - 1].CategorysB.Add(new CategoryB() { PropertyB1 = "ProbB1",PropertyB2 ="ProbB2" });
                        file.Manufacturer[file.Manufacturer.Count - 1].CategorysA.Add(new CategoryA() { PropertyA1 = "PropA11", PropertyA2="PropA22", PropertyA3 = "PropA33" });
                        file.Manufacturer[file.Manufacturer.Count - 1].CategorysB.Add(new CategoryB() { PropertyB1 = "ProbB11", PropertyB2 = "ProbB22" });
                        file.Manufacturer.Add(new Manufacturer() { Name = "second manufacturer" });
                        file.Manufacturer[file.Manufacturer.Count - 1].CategorysA.Add(new CategoryA() { PropertyA1 = "PropA1", PropertyA2 = "PropA2", PropertyA3 = "PropA3" });
                        file.Manufacturer[file.Manufacturer.Count - 1].CategorysB.Add(new CategoryB() { PropertyB1 = "ProbB1", PropertyB2 = "ProbB2" });
                        file.Manufacturer[file.Manufacturer.Count - 1].CategorysA.Add(new CategoryA() { PropertyA1 = "PropA11", PropertyA2 = "PropA22", PropertyA3 = "PropA33" });
                        file.Manufacturer[file.Manufacturer.Count - 1].CategorysB.Add(new CategoryB() { PropertyB1 = "ProbB11", PropertyB2 = "ProbB22" });
                    }
                }
                SaveSettings(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location) + @"\UserSettings");
            }
        }
        private void SetView(FileCollection files)
        {
            this._fileList = files;
            this._fileListCollectionView = new ListCollectionView(files);
            this.DataContext = _fileListCollectionView;
        }

        #region Settings Save and Load
        private void SaveSettings(string fileName)
        {
            var serializer = new XmlSerializer(typeof(FileCollection));

            using (var fs = new FileStream(fileName, FileMode.Create))
            {
                using var zipStream = new GZipStream(fs, CompressionMode.Compress);
                serializer.Serialize(zipStream, _fileList);
            }
        }

        private void OpenSettings(string fileName)
        {
            if (_fileListFile != null && fileName.Equals(_fileListFile.FullName))
            {
                MessageBox.Show("File " + fileName + " is already open");
                return;
            }
            if (!System.IO.File.Exists(fileName))
            {
                MessageBox.Show("File not exists.");
                return;
            }

            XmlSerializer serializer = new XmlSerializer(typeof(FileCollection));
            FileCollection loadedFileCollection = null;
            using (var fs = new FileStream(fileName, FileMode.Open))
            {
                using var zipStream = new GZipStream(fs, CompressionMode.Decompress);
                try
                {
                    loadedFileCollection = (FileCollection)serializer.Deserialize(zipStream);
                }
                catch (InvalidDataException ex)
                {
                    MessageBox.Show("File is invalid: " + ex.Message);
                    return;
                }
            }

            _fileList = null;

            _fileListFile = new FileInfo(fileName);
            SetView(loadedFileCollection);
        }
        #endregion Settings Save and Load
    }
}
//MainWindow.xaml
<Window x:Class="XXX.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:XXX"
        xmlns:System="clr-namespace:System;assembly=mscorlib"
    mc:Ignorable="d"
        Title="MainWindow" Height="Auto" Width="1000">
    <Window.Resources>

    </Window.Resources>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="50"/>
            <RowDefinition Height="100"/>
            <RowDefinition Height="300"/>
            <RowDefinition Height="300"/>
            <RowDefinition Height="300"/>
        </Grid.RowDefinitions>
        <DataGrid x:Name="fileDataGrid" ItemsSource="{Binding}" Margin="20,20,20,20" SelectionUnit="FullRow" AutoGenerateColumns="False" CanUserAddRows="False" IsSynchronizedWithCurrentItem="True" Grid.Row="2">
            <DataGrid.Columns>
                <DataGridTextColumn Header="FolderPath" IsReadOnly="False" Binding="{Binding FolderPath,UpdateSourceTrigger=PropertyChanged}"/>
                <DataGridTextColumn Header="Filename" IsReadOnly="false" Binding="{Binding FileName,UpdateSourceTrigger=PropertyChanged}"/>
            </DataGrid.Columns>
        </DataGrid>

        <DataGrid x:Name="manufacturerDataGrid" ItemsSource="{Binding}" Margin="20,20,20,20" SelectionUnit="FullRow" AutoGenerateColumns="False" CanUserAddRows="False" IsSynchronizedWithCurrentItem="True" Grid.Row="3">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Manufacturer Name" IsReadOnly="True" Binding="{Binding Manufacturer.Name}"/>
            </DataGrid.Columns>
        </DataGrid>

        <DataGrid x:Name="CategoryADataGrid" ItemsSource="{Binding}" Margin="20,20,20,20" SelectionUnit="FullRow" AutoGenerateColumns="False" CanUserAddRows="False" IsSynchronizedWithCurrentItem="True" Grid.Row="4">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Property A1" IsReadOnly="True" Binding="{Binding CategoryA.PropertyA1}"/>
                <DataGridTextColumn Header="Property A2" IsReadOnly="True" Binding="{Binding CategoryA.PropertyA2}"/>
                <DataGridTextColumn Header="Property A3" IsReadOnly="True" Binding="{Binding CategoryA.PropertyA3}"/>
            </DataGrid.Columns>
        </DataGrid>

        <DataGrid x:Name="CategoryBDataGrid" ItemsSource="{Binding}" Margin="20,20,20,20" SelectionUnit="FullRow" AutoGenerateColumns="False" CanUserAddRows="False" IsSynchronizedWithCurrentItem="True" Grid.Row="4" Grid.Column="1">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Property B1" IsReadOnly="True" Binding="{Binding CategoryB.PropertyB1}"/>
                <DataGridTextColumn Header="Property B2" IsReadOnly="True" Binding="{Binding CategoryB.PropertyB2}"/>
            </DataGrid.Columns>
        </DataGrid>

        <TextBox x:Name="description" Margin="20,20,20,20" TextWrapping="Wrap" AcceptsReturn="True" VerticalScrollBarVisibility="Visible" Text = "{Binding Description, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Grid.Column="1" Grid.Row="2"/>
    </Grid>
</Window>
//File.cs
using System.ComponentModel;
using System.Collections.ObjectModel;

namespace XXX.Model
{
    public class File : INotifyPropertyChanged
    {
        private string folderPath;
        private string description;
        public ObservableCollection<Manufacturer> Manufacturer { get; set; }
        public File()
        {
            Manufacturer = new ObservableCollection<Manufacturer>();
        }

        public string FolderPath
        {
            get { return folderPath; }
            set
            {
                folderPath = value;
                Changed("FolderPath");
            }
        }
        public string Description
        {
            get { return description; }
            set
            {
                description = value;
                Changed("Description");
            }
        }

        public string FileName { get; set; }

        private void Changed(string propertyName)
        {
            var handler = PropertyChanged;
            if (handler != null)
                handler(this, new PropertyChangedEventArgs(propertyName));
        }
        public event PropertyChangedEventHandler PropertyChanged;
    }
}
//FileCollection.cs
using System.Collections.ObjectModel;

namespace XXX.Model
{
    public class FileCollection : ObservableCollection<File> { }
}
//Manufacturer.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections.ObjectModel;

namespace XXX.Model
{
    public class Manufacturer
    {
        public string Name { get; set; }
        public ObservableCollection<CategoryA> CategorysA { get; set; }
        public ObservableCollection<CategoryB> CategorysB { get; set; }

        public Manufacturer()
        {
            CategorysA = new ObservableCollection<CategoryA>();
            CategorysB = new ObservableCollection<CategoryB>();
        }
        
    }
}

//CategoryA
using System;
using System.Collections.Generic;
using System.Text;

namespace XXX.Model
{
    public class CategoryA
    {
        public string PropertyA1 { get; set; }
        public string PropertyA2 { get; set; }
        public string PropertyA3 { get; set; }

    }
}
//CategoryB
using System;
using System.Collections.Generic;
using System.Text;

namespace XXX.Model
{
    public class CategoryB
    {
        public string PropertyB1 { get; set; }
        public string PropertyB2 { get; set; }

    }
}

0

There are 0 answers