I have the following challenge and hope that you can help me:
files shall be displayed in a datagrid -> works
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
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
in a fourth DataGrid, depending on what was selected in the third Datagrid, the associated properties should be displayed. -> does not work
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; }
}
}