none
Auslesen eines Arrays das innerhalb einer JSON Datei liegt RRS feed

  • Frage

  • Hallo,ich schreibe an einem Tool das eine JSON Datei einlesen soll und diese dann an ein DataGrid übergibt.
    Innerhalb der JSON liegt ein Array das in eine extra DataGrid ausgegeben werden soll.
    Ich suchs schon ewig und komm nicht auf die passende Lösung.

    Kann mir da von euch jemand weiterhelfen?

    Ich hab hier diese 3 Klassen erzeugt.Nehme ich die Teststeps raus funktioniert die Ausgabe in der ersten Datagrid wunderbar.

    Hier mein Code bisher:

    namespace TRG_2
    {
        public class Testdefinition
        {
            // properties of TestDefinition
            [JsonProperty("TestID")]
            public int TestID { get; set; }

            [JsonProperty("TestVersion")]
            public double TestVersion { get; set; }

            [JsonProperty("TestGroup")]
            public string TestGroup { get; set; }

            [JsonProperty("TestName")]
            public string TestName { get; set; }

            [JsonProperty("Result")]
            public string Result { get; set; }

            [JsonProperty("Comment")]
            public string Comment { get; set; }

            [JsonProperty("TestStep")]
            public List<string> StepDescription { get; set; }
            private List<TestStep> newList = null;



            //generate a new list with the different teststeps
            public List<TestStep> TestSteps
            {
                get => GetStepDescritions();
            }

            public List<TestStep> GetStepDescritions()
            {


                if (this.newList == null)
                {
                    this.newList = new List<TestStep>();
                    foreach (var item in StepDescription)
                    {
                        this.newList.Add(new TestStep(item));
                    }
                }
                return this.newList;
            }
        }
    }


    namespace TRG_2
    {
        public class TestStep
        {
            
            public TestStep(string stepDescription)
            {
                
                this.StepDescription = stepDescription;
            }


            public string StepDescription { get; set; }

            public bool Passed { get; set; }
            public bool Failed { get; set; }
            public bool Skipped { get; set; }
            public string Comment { get; set; }
        }
    }

    namespace TRG_2
    {
        public class DataLoader
        {
            public static List<Testdefinition> LoadTestdefinition(string FileName)
            {    
                //reads the file from the open file dialog
                StreamReader Test = new StreamReader(FileName);
                // deserializes the file in to a string
                var instances = JsonConvert.DeserializeObject<List<Testdefinition>>(Test.ReadToEnd());
                return instances;
            }        
        }
    }

    Freitag, 1. März 2019 11:37

Antworten

  • Hi,
    hier mal die ursprüngliche Demo geändert entsprechend Deiner Beschreibung.

    XAML (ohne explizite Spaltendeklaration):

    <Window x:Class="WpfApp1.Window03"
            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:WpfApp1"
            mc:Ignorable="d"
            Title="Window03" Height="450" Width="800">
      <Window.Resources>
        <local:Window03VM x:Key="vm"/>
      </Window.Resources>
        <Grid DataContext="{StaticResource vm}">
        <Grid.ColumnDefinitions>
          <ColumnDefinition/>
          <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <DataGrid Grid.Column="0" ItemsSource="{Binding View1}"/>
        <DataGrid Grid.Column="1" ItemsSource="{Binding View2}"/>
      </Grid>
    </Window>

    Dazu die Klassen:

    using Newtonsoft.Json;
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.IO;
    using System.Runtime.CompilerServices;
    using System.Windows;
    using System.Windows.Data;
    using System.Windows.Input;
    
    namespace WpfApp1
    {
      public class Window03VM : INotifyPropertyChanged
      {
    
        CollectionViewSource cvs1 = new CollectionViewSource();
        public ICollectionView View1
        {
          get
          {
            if (cvs1.Source == null)
            {
              cvs1.Source = DataLoader.LoadTestdefinition(@"Window03JSon.txt");
              cvs1.View.CurrentChanged += View_CurrentChanged;
            }
            return cvs1.View;
          }
        }
    
        CollectionViewSource cvs2 = new CollectionViewSource();
        public ICollectionView View2 { get { return cvs2.View; } }
    
        private void View_CurrentChanged(object sender, EventArgs e)
        {
          cvs2.Source = ((Testdefinition)((ICollectionView)sender).CurrentItem).TestSteps;
          OnPropertyChanged(nameof(View2));
        }
    
        #region  OnPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged([CallerMemberName] string propName = "") =>
          PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
        #endregion
      }
        public class Testdefinition
        {
          // properties of TestDefinition
          [JsonProperty("TestID")]
          public int TestID { get; set; }
    
          [JsonProperty("TestVersion")]
          public double TestVersion { get; set; }
    
          [JsonProperty("TestGroup")]
          public string TestGroup { get; set; }
    
          [JsonProperty("TestName")]
          public string TestName { get; set; }
    
          [JsonProperty("Result")]
          public string Result { get; set; }
    
          [JsonProperty("Comment")]
          public string Comment { get; set; }
    
          [JsonProperty("TestSteps")]
          public string[] StepArray { get; set; }
    
          [JsonProperty("none")]
          public List<TestStep> TestSteps
          {
            get
            {
              List<TestStep> s = new List<TestStep>();
              for (int i = 0; i < StepArray.Length; i++) s.Add(new TestStep() { StepDescription = StepArray[i] });
              return s;
            }
          }
        }
    
        public class TestStep
        {
          public string StepDescription { get; set; }
          public bool Passed { get; set; } = false;
          public bool Failed { get; set; } = false;
          public bool Skipped { get; set; } = false;
          public string Comment { get; set; }
        }
    
        public class DataLoader
        {
          public static List<Testdefinition> LoadTestdefinition(string FileName)
          {
            //reads the file from the open file dialog
            StreamReader Test = new StreamReader(FileName);
            // deserializes the file in to a string
            var instances = JsonConvert.DeserializeObject<List<Testdefinition>>(Test.ReadToEnd());
            return instances;
          }
        }
    }


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP für Developer Technologies)
    Meine Homepage mit Tipps und Tricks

    Samstag, 2. März 2019 06:04

Alle Antworten

  • Hi,
    und wie sieht die Bindung? Vom LoadTestdefinition bekommst Du eine Liste mit Objekten vom Typ "Testdefinition". Aus den Eigenschaften des Typs "Testdefinition" kannst Du Spalten binden oder einfach implizit alle Spalten binden.

    Du solltest aber auch schreiben, welche Art von Projekt Du hast, da es das DataGrid in WindowsForms, in WPF usw. gibt.

    Wichtig wäre auch ein Muster für die JSon-Daten, um zu erkennen, wie die Liste für "TestSteps" übergeben wird.


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP für Developer Technologies)
    Meine Homepage mit Tipps und Tricks


    Freitag, 1. März 2019 13:47
  • Sorry, hab ich glatt vergessen, es handelt sich um eine WPF Anwendung.
    Daten Bindung funktioniert soweit auch beim ersten DataGrid, nur bei den Steps hab ich da den ein oder anderen Denkfehler denk ich mal.

    TestID, TestGroup,TestVersion und TestName werden in einem eigenen DataGrid ausgegeben.
    TestSteps sollen in einen eigenes DataGrid weil da noch 3 Spalten mit boolschen Werten dran kommen wo man die Steps bewerten kann

    Hier die JSON - Daten:

    Hier die JSON Daten:

    [{"TestID":1,
    "TestVersion":1.0,
    "TestGroup":"Group3",
    "TestName":"Sample-Test",
    "TestSteps":[
    "1.Appl starten(Applikation ist gestartet)",
    "2.Datei laden(Datei ist geladen und wird angezeigt)",
    "3.Datei ändern",
    "4.Datei speichern"],
    "Result":"all Tests are passed",
    "Comment":"Applikation in vollem Umfang einsatzbereit"},
    {"TestID":2,
    "TestVersion":1.0,
    "TestGroup":"Group2",
    "TestName":"Sample-Test",
    "TestSteps":[
    "1.Appl starten(Applikation ist gestartet)",
    "2.Datei laden(Datei ist geladen und wird angezeigt)",
    "3.Datei ändern",
    "4.Datei speichern"],
    "Result":"all Tests are passed",
    "Comment":"Applikation in vollem Umfang einsatzbereit"},
    {"TestID":3,
    "TestVersion":1.0,
    "TestGroup":"Group7",
    "TestName":"Sample-Test",
    "TestSteps":[
    "1.Appl starten(Applikation ist gestartet)",
    "2.Datei laden(Datei ist geladen und wird angezeigt)",
    "3.Datei ändern",
    "4.Datei speichern"],
    "Result":"all Tests are passed",
    "Comment":"Applikation in vollem Umfang einsatzbereit"},
    {"TestID":4,
    "TestVersion":1.0,
    "TestGroup":"Group3",
    "TestName":"Sample-Test",
    "TestSteps":[
    "1.Appl starten(Applikation ist gestartet)",
    "2.Datei laden(Datei ist geladen und wird angezeigt)",
    "3.Datei ändern",
    "4.Datei speichern"],
    "Result":" all Tests are passed", "Comment":"Applikation in vollem Umfang einsatzbereit"}]



    Freitag, 1. März 2019 13:52
  • Hi,
    die TestSteps sind ein String-Array.

        public class Testdefinition
        {
          // properties of TestDefinition
          [JsonProperty("TestID")]
          public int TestID { get; set; }
    
          [JsonProperty("TestVersion")]
          public double TestVersion { get; set; }
    
          [JsonProperty("TestGroup")]
          public string TestGroup { get; set; }
    
          [JsonProperty("TestName")]
          public string TestName { get; set; }
    
          [JsonProperty("Result")]
          public string Result { get; set; }
    
          [JsonProperty("Comment")]
          public string Comment { get; set; }
    
          [JsonProperty("TestSteps")]
          public string[] StepArray { get; set; }
        }
    

    Was willst Du erreichen?


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP für Developer Technologies)
    Meine Homepage mit Tipps und Tricks

    Freitag, 1. März 2019 19:30
  • Hi,

    ich hab 2 DataGridViews, in einem davon sollen

    die TestSteps untereinander angezeigt werden.
    Mit den Sachen wie ID und so klappt das auch schon.
    Nur komm ich grade nicht an der Stelle weiter wie ich die Daten
    von der JSON für die TestSteps raus bekomme und in das DataGridView rein

    Freitag, 1. März 2019 21:29
  • Hi,

    so richtig verstanden habe ich dich noch immer nicht. Aber hier mal eine kleine Demo. Auf der linken Seite werden TestID usw. angezeigt.

    Auf der rechten Seite werden die Einträge des TestSteps-Array des selektierten "Tests" angezeigt.

    Window:

    <Window x:Class="WpfApp22.Window83"
            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:WpfApp22"
            mc:Ignorable="d"
            Title="Window83" Height="450" Width="800">
        <Window.Resources>
            <local:Window83VM x:Key="vm"/>
        </Window.Resources>
        <Grid DataContext="{StaticResource vm}">
            <Grid.ColumnDefinitions>
                <ColumnDefinition/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>
            <DataGrid ItemsSource="{Binding LeftView}" AutoGenerateColumns="False" IsReadOnly="True">
                <DataGrid.Columns>
                    <DataGridTextColumn Header="TestID" Binding="{Binding TestID}" />
                    <DataGridTextColumn Header="TestVersion" Binding="{Binding TestVersion}" />
                    <DataGridTextColumn Header="TestGroup" Binding="{Binding TestGroup}" />
                    <DataGridTextColumn Header="TestName" Binding="{Binding TestName}" />
                    <DataGridTextColumn Header="Result" Binding="{Binding Result}" />
                    <DataGridTextColumn Header="Comment" Binding="{Binding Comment}" />
                </DataGrid.Columns>
            </DataGrid>
            <DataGrid ItemsSource="{Binding RightView}" AutoGenerateColumns="True" IsReadOnly="True" Grid.Column="1"/>
        </Grid>
    </Window>
    

    ViewModel:

    using System;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Runtime.CompilerServices;
    using System.Windows.Data;
    
    namespace WpfApp22
    {
        public class Window83VM : INotifyPropertyChanged
        {
            public Window83VM()
            {
                LeftView.CurrentChanged += new EventHandler(OnDataICVCurrentChanged);
            }
    
            private CollectionViewSource LeftDataViewSource = new CollectionViewSource();
            public ICollectionView LeftView
            {
                get
                {
                    if (LeftDataViewSource.Source == null)
                    {
                        var col = GetData();
                        LeftDataViewSource.Source = col;
                    }
                    return LeftDataViewSource.View;
                }
            }
            private ObservableCollection<Window83Model> GetData()
            {
                ObservableCollection<Window83Model> DataCollection = new ObservableCollection<Window83Model>();
                DataCollection = Helpers.JsonSerialization.ReadFromJsonFile<ObservableCollection<Window83Model>>(@"C:\Temp\test.json");
                return DataCollection;
            }
    
            private CollectionViewSource RightDataViewSource = new CollectionViewSource();
            public ICollectionView RightView
            {
                get
                {
                    if (RightDataViewSource.Source == null)
                    {
                        RightDataViewSource.Source = RightDataCollection;
                    }
                    return RightDataViewSource.View;
                }
            }
    
            ObservableCollection<Window83ModelRight> RightDataCollection = new ObservableCollection<Window83ModelRight>();
            private void OnDataICVCurrentChanged(object sender, EventArgs e)
            {
                var currItm = (Window83Model)LeftView.CurrentItem;
                RightDataCollection.Clear();
                foreach (var x in currItm.StepArray)
                    RightDataCollection.Add(new Window83ModelRight { TestStep = x });
            }
    
            #region  OnPropertyChanged
            public event PropertyChangedEventHandler PropertyChanged;
            private void OnPropertyChanged([CallerMemberName] string propName = "") =>
              PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
            #endregion
        }
    }
    

    Models:

    using Newtonsoft.Json;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace WpfApp22
    {
        public class Window83Model
        {
            [JsonProperty("TestID")]
            public int TestID { get; set; }
    
            [JsonProperty("TestVersion")]
            public double TestVersion { get; set; }
    
            [JsonProperty("TestGroup")]
            public string TestGroup { get; set; }
    
            [JsonProperty("TestName")]
            public string TestName { get; set; }
    
            [JsonProperty("Result")]
            public string Result { get; set; }
    
            [JsonProperty("Comment")]
            public string Comment { get; set; }
    
            [JsonProperty("TestSteps")]
            public string[] StepArray { get; set; }
        }
    
        public class Window83ModelRight
        {
            public string TestStep { get; set; }
            public override string ToString()
            {
                return TestStep.ToString();
            }
        }
    }
    

    Und zum Schluss noch die Methoden, die ich zur De/Serialisierung nutze:

    using System.IO;
    
    namespace Helpers
    {
        /// <summary>
        /// Functions for performing common Json Serialization operations.
        /// <para>Requires the Newtonsoft.Json assembly (Json.Net package in NuGet Gallery) to be referenced in your project.</para>
        /// <para>Only public properties and variables will be serialized.</para>
        /// <para>Use the [JsonIgnore] attribute to ignore specific public properties or variables.</para>
        /// <para>Object to be serialized must have a parameterless constructor.</para>
        /// </summary>
        public static class JsonSerialization
        {
            /// <summary>
            /// Writes the given object instance to a Json file.
            /// <para>Object type must have a parameterless constructor.</para>
            /// <para>Only Public properties and variables will be written to the file. These can be any type though, even other classes.</para>
            /// <para>If there are public properties/variables that you do not want written to the file, decorate them with the [JsonIgnore] attribute.</para>
            /// </summary>
            /// <typeparam name="T">The type of object being written to the file.</typeparam>
            /// <param name="filePath">The file path to write the object instance to.</param>
            /// <param name="objectToWrite">The object instance to write to the file.</param>
            /// <param name="append">If false the file will be overwritten if it already exists. If true the contents will be appended to the file.</param>
            public static void WriteToJsonFile<T>(string filePath, T objectToWrite, bool append = false) where T : new()
            {
                TextWriter writer = null;
                try
                {
                    var contentsToWriteToFile = Newtonsoft.Json.JsonConvert.SerializeObject(objectToWrite);
                    writer = new StreamWriter(filePath, append);
                    writer.Write(contentsToWriteToFile);
                }
                finally
                {
                    try
                    {
                        if (writer != null)
                            writer.Close();
                    }
                    catch { }
                }
            }
    
            /// <summary>
            /// Reads an object instance from an Json file.
            /// <para>Object type must have a parameterless constructor.</para>
            /// </summary>
            /// <typeparam name="T">The type of object to read from the file.</typeparam>
            /// <param name="filePath">The file path to read the object instance from.</param>
            /// <returns>Returns a new instance of the object read from the Json file.</returns>
            public static T ReadFromJsonFile<T>(string filePath) where T : new()
            {
                TextReader reader = null;
                try
                {
                    reader = new StreamReader(filePath);
                    var fileContents = reader.ReadToEnd();
                    return Newtonsoft.Json.JsonConvert.DeserializeObject<T>(fileContents);
                }
                finally
                {
                    if (reader != null)
                        reader.Close();
                }
            }
        }
    }
    

    Vielleicht hilft es dir weiter.

    Gruß


    Freiberufler im Bereich Softwareentwicklung Von der PLC und Robotik zu VB.NET & C#, vorrangig WPF und UWP

    Freitag, 1. März 2019 23:31
  • Hi,
    hier mal eine Demo:

    XAML (ohne explizite Auswahl der anzuzeigenden Spalten)

    <Window x:Class="WpfApp1.Window03"
            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:WpfApp1"
            mc:Ignorable="d"
            Title="Window03" Height="450" Width="800">
      <Window.Resources>
        <local:Window03VM x:Key="vm"/>
      </Window.Resources>
        <Grid DataContext="{StaticResource vm}">
        <Grid.ColumnDefinitions>
          <ColumnDefinition/>
          <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <DataGrid Grid.Column="0" ItemsSource="{Binding View1}"/>
        <DataGrid Grid.Column="1" ItemsSource="{Binding View2}"/>
      </Grid>
    </Window>

    Dazu die Klassen:

    using Newtonsoft.Json; using System; using System.Collections.Generic; using System.ComponentModel; using System.IO; using System.Runtime.CompilerServices; using System.Windows; using System.Windows.Data; using System.Windows.Input; namespace WpfApp1 { public class Window03VM : INotifyPropertyChanged { CollectionViewSource cvs1 = new CollectionViewSource(); public ICollectionView View1 { get { if (cvs1.Source == null) { cvs1.Source = DataLoader.LoadTestdefinition(@"Window03JSon.txt"); cvs1.View.CurrentChanged += View_CurrentChanged; } return cvs1.View; } } CollectionViewSource cvs2 = new CollectionViewSource(); public ICollectionView View2 { get { return cvs2.View; } } private void View_CurrentChanged(object sender, EventArgs e) { cvs2.Source = ((Testdefinition)((ICollectionView)sender).CurrentItem).TestSteps; OnPropertyChanged(nameof(View2)); } #region OnPropertyChanged public event PropertyChangedEventHandler PropertyChanged; private void OnPropertyChanged([CallerMemberName] string propName = "") => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName)); #endregion   }

    public class Testdefinition { // properties of TestDefinition [JsonProperty("TestID")] public int TestID { get; set; } [JsonProperty("TestVersion")] public double TestVersion { get; set; } [JsonProperty("TestGroup")] public string TestGroup { get; set; } [JsonProperty("TestName")] public string TestName { get; set; } [JsonProperty("Result")] public string Result { get; set; } [JsonProperty("Comment")] public string Comment { get; set; } [JsonProperty("TestSteps")] public string[] StepArray { get; set; } [JsonProperty("none")] public List<KeyValuePair<int, string>> TestSteps { get { List<KeyValuePair<int, string>> s = new List<KeyValuePair<int, string>>(); for (int i = 0; i < StepArray.Length; i++) s.Add(new KeyValuePair<int, string>(i + 1, StepArray[i])); return s; } } } public class DataLoader { public static List<Testdefinition> LoadTestdefinition(string FileName) { //reads the file from the open file dialog StreamReader Test = new StreamReader(FileName); // deserializes the file in to a string var instances = JsonConvert.DeserializeObject<List<Testdefinition>>(Test.ReadToEnd()); return instances; } } }



    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP für Developer Technologies)
    Meine Homepage mit Tipps und Tricks


    Samstag, 2. März 2019 05:22
  • Hallo,

    ist etwas schwieriger zu erklären.
    Ich habe eine WPF Anwendung wo mittels open File Dialog die JSON Daten eingelesen werden.
    Nachdem sie eingelesen wurden, sollen sie getrennt in 2 DataGridViews angezeigt werden.
    Im ersten DataGridView sind TestID,TestGroup,TestName,TestVersion, und Comment.
    Result fliegt an dieser Stelle komplett raus, da ja die Bewertung im zweit DGV statt findet.
    In der zweiten DataGridView sollen dann die TestSteps untereinander stehen, wo dann hinter jedem
    TestStep 3 Spalten kommen wo man den TestStep als passed,failed oder skipped auswerten kann.

    Am ende soll dann daraus wieder eine JSON Datei erstellt werden, die später dann in das XML Format serializiert werden soll,ber das ist ein anderer Schuh.
    Erstmal danke für deine Unterstützung, hatte ich bisher ja vergessen


    Samstag, 2. März 2019 05:42
  • Hi,
    hier mal die ursprüngliche Demo geändert entsprechend Deiner Beschreibung.

    XAML (ohne explizite Spaltendeklaration):

    <Window x:Class="WpfApp1.Window03"
            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:WpfApp1"
            mc:Ignorable="d"
            Title="Window03" Height="450" Width="800">
      <Window.Resources>
        <local:Window03VM x:Key="vm"/>
      </Window.Resources>
        <Grid DataContext="{StaticResource vm}">
        <Grid.ColumnDefinitions>
          <ColumnDefinition/>
          <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <DataGrid Grid.Column="0" ItemsSource="{Binding View1}"/>
        <DataGrid Grid.Column="1" ItemsSource="{Binding View2}"/>
      </Grid>
    </Window>

    Dazu die Klassen:

    using Newtonsoft.Json;
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.IO;
    using System.Runtime.CompilerServices;
    using System.Windows;
    using System.Windows.Data;
    using System.Windows.Input;
    
    namespace WpfApp1
    {
      public class Window03VM : INotifyPropertyChanged
      {
    
        CollectionViewSource cvs1 = new CollectionViewSource();
        public ICollectionView View1
        {
          get
          {
            if (cvs1.Source == null)
            {
              cvs1.Source = DataLoader.LoadTestdefinition(@"Window03JSon.txt");
              cvs1.View.CurrentChanged += View_CurrentChanged;
            }
            return cvs1.View;
          }
        }
    
        CollectionViewSource cvs2 = new CollectionViewSource();
        public ICollectionView View2 { get { return cvs2.View; } }
    
        private void View_CurrentChanged(object sender, EventArgs e)
        {
          cvs2.Source = ((Testdefinition)((ICollectionView)sender).CurrentItem).TestSteps;
          OnPropertyChanged(nameof(View2));
        }
    
        #region  OnPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged([CallerMemberName] string propName = "") =>
          PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
        #endregion
      }
        public class Testdefinition
        {
          // properties of TestDefinition
          [JsonProperty("TestID")]
          public int TestID { get; set; }
    
          [JsonProperty("TestVersion")]
          public double TestVersion { get; set; }
    
          [JsonProperty("TestGroup")]
          public string TestGroup { get; set; }
    
          [JsonProperty("TestName")]
          public string TestName { get; set; }
    
          [JsonProperty("Result")]
          public string Result { get; set; }
    
          [JsonProperty("Comment")]
          public string Comment { get; set; }
    
          [JsonProperty("TestSteps")]
          public string[] StepArray { get; set; }
    
          [JsonProperty("none")]
          public List<TestStep> TestSteps
          {
            get
            {
              List<TestStep> s = new List<TestStep>();
              for (int i = 0; i < StepArray.Length; i++) s.Add(new TestStep() { StepDescription = StepArray[i] });
              return s;
            }
          }
        }
    
        public class TestStep
        {
          public string StepDescription { get; set; }
          public bool Passed { get; set; } = false;
          public bool Failed { get; set; } = false;
          public bool Skipped { get; set; } = false;
          public string Comment { get; set; }
        }
    
        public class DataLoader
        {
          public static List<Testdefinition> LoadTestdefinition(string FileName)
          {
            //reads the file from the open file dialog
            StreamReader Test = new StreamReader(FileName);
            // deserializes the file in to a string
            var instances = JsonConvert.DeserializeObject<List<Testdefinition>>(Test.ReadToEnd());
            return instances;
          }
        }
    }


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP für Developer Technologies)
    Meine Homepage mit Tipps und Tricks

    Samstag, 2. März 2019 06:04
  • Hi Peter,

    ich glaub ich lauf grad irgendwie in die falsche Richtung.
    Hab es versucht umzusetzten, bekomm aber den Fehler das :
    "Der Name "Window03VM"ist im Namespace clr-Namespace TRG_3 nicht vorhanden ist.
    TRG_3 is meine Solution.
    Bin im MVVM Konzept absoluter Neuling ,sorry

    Grüße

    Mein bisheriger XAML Code:
    <Window x:Class="TRG_2.MainWindow" ResizeMode="CanMinimize"
            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:TRG_2"
            mc:Ignorable="d"
           
            Title="Test Result Generator " Height="800" Width="1014.463">
        <Grid Background="LightGray" Margin="0,0,0,-4">
            <Grid.ColumnDefinitions>
                <ColumnDefinition/>
                <ColumnDefinition/>
                <ColumnDefinition/>
                <ColumnDefinition/>

            </Grid.ColumnDefinitions>

            <Grid.RowDefinitions>
                <RowDefinition/>
                <RowDefinition/>
                <RowDefinition/>
                <RowDefinition/>
                <RowDefinition/>
                <RowDefinition/>
            </Grid.RowDefinitions>
            <TextBox x:Name="TxtFile" HorizontalAlignment="Left"  BorderThickness="5" Height="35" FontSize="18" Grid.ColumnSpan="3" Margin="25,44,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="628"/>
            <Button x:Name="BtnBrowse" Content="Browse" Grid.Column="2" FontSize="18" HorizontalAlignment="Left" Margin="167,44,0,0" VerticalAlignment="Top" Width="75" Height="35" Click="BtnBrowse_Click"/>
            <TextBox x:Name="TxtUser" HorizontalAlignment="Left" BorderThickness="5" FontSize="18" Height="40" Margin="25,102,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="193" RenderTransformOrigin="0.518,0.241" Grid.RowSpan="2"/>
            <Label x:Name="LblCurrentUser" Content="current User" FontSize="18" HorizontalAlignment="Left" Margin="239,102,0,0" VerticalAlignment="Top" RenderTransformOrigin="0.034,-0.183" Height="40" Width="120" Grid.ColumnSpan="2" Grid.RowSpan="2"/>
            <DatePicker x:Name="Dtp1" HorizontalAlignment="Left" Focusable="True" FontSize="18" Margin="25,30,0,0" VerticalAlignment="Top" Width="163" Height="38" Grid.Row="1"/>
            <TextBox x:Name="TxtComment" BorderThickness="5" FontSize="18" HorizontalAlignment="Left" Height="116" Margin="25,10,0,0" Grid.Row="4" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="907" Grid.ColumnSpan="4"/>
            
            <Button x:Name="BtnExport" BorderThickness="5" FontSize="18" Content="Export" HorizontalAlignment="Left" Margin="24,49,0,0" Grid.Row="5" VerticalAlignment="Top" Width="96" Grid.Column="3"/>
            <Button x:Name="Btncancel" BorderThickness="5"  FontSize="18" Content="cancel" Grid.Column="3" HorizontalAlignment="Right" Margin="0,49,10,44" Grid.Row="5" Width="87" Click="Btncancel_Click"/>
            <Label Content="Testdefinition" FontSize="18" HorizontalAlignment="Left" Margin="27,73,0,0" Grid.Row="1" VerticalAlignment="Top"/>
            <Label Content="Comment" FontSize="18" HorizontalAlignment="Left" Margin="27,105,0,0" Grid.Row="3" VerticalAlignment="Top" Grid.RowSpan="2"/>
          
            <DataGrid  BorderThickness="5" ItemsSource="{Binding TestDefinition}" AutoGenerateColumns="false" CanUserAddRows="True"  HorizontalAlignment="Left" Height="83" Margin="25,107,0,0" Grid.Row="1" VerticalAlignment="Top" Width="907" Grid.ColumnSpan="4" Grid.RowSpan="2">
                <DataGrid.Columns>
                    <DataGridTextColumn Header="TestID" Binding="{Binding TestID}" Width="auto"/>
                    <DataGridTextColumn Header="TestName" Binding="{Binding TestName}" Width="auto"/>
                    <DataGridTextColumn Header="TestVersion" Binding="{Binding TestVersion}"   Width="auto"/>
                    <DataGridTextColumn Header="TestGroup" Binding="{Binding TestGroup}" Width="auto"/>
                    <DataGridTextColumn Header=" Result" Binding="{Binding Result}" Width="auto"/>
                    <DataGridTextColumn Header="Comment" Binding="{Binding Comment}"  Width="auto"/>


                </DataGrid.Columns>
            </DataGrid>
            <DataGrid x:Name="DtgTeststeps" ItemsSource="{Binding TestDefiniton}" CanUserAddRows="True" BorderThickness="5" AutoGenerateColumns="False"  HorizontalAlignment="Left" Height="100" Margin="25,118,0,0" Grid.Row="2" VerticalAlignment="Top" Width="907" Grid.ColumnSpan="4" Grid.RowSpan="2">
                <DataGrid.Columns>
                    <DataGridTextColumn Header="Teststeps" Binding="{Binding TestSteps}" />

                    <DataGridTemplateColumn Header="Passed">
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <CheckBox IsChecked="{Binding Passed, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"/>
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>
                    <DataGridTemplateColumn Header="Failed">
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <CheckBox IsChecked="{Binding Failed, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"/>
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>
                    <DataGridTemplateColumn Header="Skipped">
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <CheckBox IsChecked="{Binding Skipped, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"/>
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>
                </DataGrid.Columns>
            </DataGrid>
            <Label Content="Teststeps" FontSize="18" HorizontalAlignment="Left" Margin="27,84,0,0" Grid.Row="2" VerticalAlignment="Top" Width="115" Height="35"/>
            <Label Grid.ColumnSpan="2" Content="Test Result Generator" FontSize="28" FontFamily="Verdana" FontStyle="Italic" FontWeight="ExtraBlack" HorizontalAlignment="Left" Margin="0,77,0,0" VerticalAlignment="Top" Height="52" Width="363" Grid.Row="5"/>
        </Grid>
    </Window>




    Samstag, 2. März 2019 08:38
  • Hi,
    wenn Window03VM im Namensraum nicht gefunden wird, dann heißt die Klasse bei Dir anders oder sie befindet sich in einem anderen Namensraum. Das hat erst einmal nichts mit MVVM zu tun. Ich kann auch nicht erkennen, wo Du in Deinem XAML diese Klasse nutzt.

    Unklar ist, wie Du den DataContext zuweist.

    Die ItemsSources der beiden DataGrids nutzen die gleiche Quelle "Testdefinition". Wie ist das zu verstehen?


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP für Developer Technologies)
    Meine Homepage mit Tipps und Tricks

    Samstag, 2. März 2019 10:57
  • Hallo Peter,

    aus der Testdefinitionsdatei(die JSON Daten) werden diese herausgelesen.
    Das ganze soll dann in 2 unterschiedlichen DGV´s ausgegeben werden.
    Hab es mit deinem Code versucht, da wird jedoch auch alles an die erste DGV übergeben. Die
    linke Seite der WPF bleibt leer.
    Ist wohl doch komplizierter als ich dachte.
    Ich hole mittels open File Dilog die Json Daten ins Programm.
    Diese soll dann so bearbeitet werden das die 2 DataGridViews mit den oben angegebenen
    Inhalten befüllt werden.
    Ich denk ab und zu einfach zu kompliziert wie es aussieht.

    Grüße

    P.S.: Der XAML Code ist der Aufbau wie das ganze dann letzendlich aussehen soll und womit ich bis jetzt versucht habe das ganze ans laufen zu kriegen

    P.s.s: Hab bemerkt das ich ein snippet vergessen hab , sorry dafür
    Hier ist es:
    namespace TRG_2.ViewModel
    {
        public class TRGViewModel : INotifyPropertyChanged
        {
            private List<Testdefinition> testDefinition;
            public List<Testdefinition> TestDefinition
            {
                get { return testDefinition; }
                set
                {
                    if (this.testDefinition != value)
                    {
                        this.testDefinition = value;
                        this.FirePropertyChanged(nameof(this.TestDefinition));
                    }
                }
            }

            public event PropertyChangedEventHandler PropertyChanged;

            // gives every change to the GUI
            private void FirePropertyChanged(string propertyName)
            {
                if (this.PropertyChanged!=null)
                {
                    this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                }
            }

            internal void  LoadTestDefinition()
            {
                //Browse the Filesystem and open the selected File in the Textbox
                OpenFileDialog ofd = new OpenFileDialog();
                ofd.DefaultExt = ".json";

                if (ofd.ShowDialog() == true)
                {
                   // takes the selected File from the open file dialog and load in to the List TestDefinition
                    TestDefinition = DataLoader.LoadTestdefinition(ofd.FileName);
                    
                }
            }
        }


    Samstag, 2. März 2019 11:38
  • Hi,
    ich empfehle Dir, einfach mal meinen Code unverändert (außer Namensräume und Namen des Window) in ein leeres Projekt zu kopieren und mal zu testen. Das rechte DataGrid zeigt in meinem Beispiel erst etwas an, wenn im linken DataGrid eine Zeile angeklickt wird.


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP für Developer Technologies)
    Meine Homepage mit Tipps und Tricks

    Samstag, 2. März 2019 12:31
  • Hi Peter,

    habs ja genau so gemacht um es zu testen, war nur im ersten Augenblick verwirrt
    das die linke Seite leer bleibt.
    Ok jetzt hats gefunkt, hab es in mein Prog teilweise übernommen und es funktioniert.
    Hast mir echt viel damit geholfen.
    Recht herzlichen dank für deine Hilfe und deine Geduld.

    Grüße

    Samstag, 2. März 2019 15:43
  • Hallo Peter, mir ist leider erst heute aufgefallen, daß bei dem Prog wenn man es aufruft, es nicht direkt nach Aufruf des ersten Test funktioniert.
    Heißt Prog starten, direkt auf Tesz Nummer 1 klicken und datagrid 2 bleibt leer.
    Liegt denk ich an dem CurrentChanged, finde aber keine adequate Lösung für das Problem.hast du da einen Tip für mich?

    Danke

    Viele Grüße

    Montag, 4. März 2019 11:47
  • Hi,
    das Programm soll als Anregung dienen. Wenn da etwas konkretes passieren soll, dann muss man das erst einmal definieren und dann implementieren. Ich vermute, Dir missfällt, dass es zum Start keinen selektierten Eintrag gibt. Das kannst Du ändern in meiner Demo beispielsweise so:

        CollectionViewSource cvs1 = new CollectionViewSource();
        public ICollectionView View1
        {
          get
          {
            if (cvs1.Source == null)
            {
              cvs1.Source = DataLoader.LoadTestdefinition(@"Window03JSon.txt");
              cvs1.View.CurrentChanged += View_CurrentChanged;
              cvs1.View.MoveCurrentToFirst();
              View_CurrentChanged(cvs1.View, null);
            }
            return cvs1.View;
          }
        }


    --
    Viele Grüsse / Best Regards
    Peter Fleischer (former MVP for Developer Technologies)
    Homepage, Tipps, Tricks

    Montag, 4. März 2019 12:35
  • Hallo Peter, nein darum das nichts selektiert ist, ist nicht das Thema. Das hab ich allein hinbekommen das der erste Eintrag automatisch gewählt wird.
    Es geht darum , das wenn das Programm startet ja die rechte DGV leer ist.
    Selektierst du jetzt nach starten den ersten Testeintrag in der DGV wo alle Test gelistet sind ,dann passiert nichts.
    Man muß erst in der rechten DGV einen anderen Test (ID 2,3 oder 4) selektieren bevor man den Test 1 selektieren kann.
    Hoffe du verstehst was ich meine

    grüße

    Montag, 4. März 2019 12:50
  • Hi,
    aber die letzte Ergänzung umgeht genau dieses Problem. Es wird beim Start auf die erste Zeile positioniert und dann auch die Details angezeigt. Mit einem wiederholten Klick auf die erste Zeile ändert sich natürlich nichts, da ja schon angezeigt wird. Was willst Du denn wirklich? 

    --
    Viele Grüsse / Best Regards
    Peter Fleischer (former MVP for Developer Technologies)
    Homepage, Tipps, Tricks

    Montag, 4. März 2019 13:24
  • Hi Peter, DataGrid sollte beim starten beide leer sein.
    Testdefinition wird mittels OpenFileDialog geladen und dann in der linken DGV angezeigt.
    Erst wenn einer der Tests selektiert wurde (sollte auch mit TestID 1 klappen) sollte in der rechten DGV was angezeigt werden.
    Thats all

    grüße

    Montag, 4. März 2019 13:43
  • Hi,
    wenn Du es so haben willst, dann mach das wie folgt. Ich habe einen Button eingebaut, der erst das Laden initiiert.

    XAML:

    <Window x:Class="WpfApp1.Window03"
            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:WpfApp1"
            mc:Ignorable="d"
            Title="Window03" Height="450" Width="800">
      <Window.Resources>
        <local:Window03VM x:Key="vm"/>
      </Window.Resources>
      <Grid DataContext="{StaticResource vm}">
        <Grid.RowDefinitions>
          <RowDefinition Height="Auto"/>
          <RowDefinition/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
          <ColumnDefinition/>
          <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Button Content="Laden" Command="{Binding Cmd}" Margin="5"/>
        <DataGrid Grid.Row="1" Grid.Column="0" ItemsSource="{Binding View1}"/>
        <DataGrid Grid.Row="1" Grid.Column="1" ItemsSource="{Binding View2}"/>
      </Grid>
    </Window>

    Dazu die Klassen:

    using Newtonsoft.Json;
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.IO;
    using System.Runtime.CompilerServices;
    using System.Windows;
    using System.Windows.Data;
    using System.Windows.Input;
    
    namespace WpfApp1
    {
      public class Window03VM : INotifyPropertyChanged
      {
    
        public ICommand Cmd
        {
          get
          {
            return new RelayCommand<string>((state) =>
            {
              cvs1.Source = DataLoader.LoadTestdefinition(@"Window03JSon.txt");
              cvs1.View.CurrentChanged += View_CurrentChanged;
              cvs1.View.MoveCurrentTo(null);
              OnPropertyChanged(nameof(View1));
            });
          }
        }
    
        CollectionViewSource cvs1 = new CollectionViewSource();
        public ICollectionView View1 { get { return cvs1.View; } }
    
        CollectionViewSource cvs2 = new CollectionViewSource();
        public ICollectionView View2 { get { return cvs2.View; } }
    
        private void View_CurrentChanged(object sender, EventArgs e)
        {
          cvs2.Source = ((Testdefinition)((ICollectionView)sender).CurrentItem)?.TestSteps;
          OnPropertyChanged(nameof(View2));
        }
    
        #region  OnPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged([CallerMemberName] string propName = "") =>
          PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
        #endregion
    
        public class Testdefinition
        {
          // properties of TestDefinition
          [JsonProperty("TestID")]
          public int TestID { get; set; }
    
          [JsonProperty("TestVersion")]
          public double TestVersion { get; set; }
    
          [JsonProperty("TestGroup")]
          public string TestGroup { get; set; }
    
          [JsonProperty("TestName")]
          public string TestName { get; set; }
    
          [JsonProperty("Result")]
          public string Result { get; set; }
    
          [JsonProperty("Comment")]
          public string Comment { get; set; }
    
          [JsonProperty("TestSteps")]
          public string[] StepArray { get; set; }
    
          [JsonProperty("none")]
          public List<TestStep> TestSteps
          {
            get
            {
              List<TestStep> s = new List<TestStep>();
              for (int i = 0; i < StepArray.Length; i++) s.Add(new TestStep() { StepDescription = StepArray[i] });
              return s;
            }
          }
        }
    
        public class TestStep
        {
          public string StepDescription { get; set; }
          public bool Passed { get; set; } = false;
          public bool Failed { get; set; } = false;
          public bool Skipped { get; set; } = false;
          public string Comment { get; set; }
        }
    
        public class DataLoader
        {
          public static List<Testdefinition> LoadTestdefinition(string FileName)
          {
            //reads the file from the open file dialog
            StreamReader Test = new StreamReader(FileName);
            // deserializes the file in to a string
            var instances = JsonConvert.DeserializeObject<List<Testdefinition>>(Test.ReadToEnd());
            return instances;
          }
        }
      }
    }



    --
    Viele Grüsse / Best Regards
    Peter Fleischer (former MVP for Developer Technologies)
    Homepage, Tipps, Tricks

    Montag, 4. März 2019 14:33
  • Hallo Peter,

    bin nun ein ganzes Stück weiter und das Prog tut bis jetzt auch das was es soll.
    Es startet mit 2 leeren DtaGrids und die 2te wird auch erst befüllt sobald man in der
    ersten eine Zeile selektiert hat.
    Nun steh ich vor dem Problem das ich die Daten aus dem DataGRid wieder raus haben will und als JSON speichern will.
    Bzw. will ich erreichen das wenn ich in einem der Datagrid´s was ändere es zurückgeschreiben und gespeichert wird.
    Hab schon sämtliche Tips und Tricks die Google hierzu ausspuckt versucht, enden aber fast alle in einem Fehler oder führen nicht zum Ziel.
    Hat du da einen entscheidenden Tip für mich?

    Danke

    Viele Grüße

    Freitag, 8. März 2019 09:53
  • Hi,
    hier mal eine Demo, in der die geänderten Daten zurück gespeichert werden. Dabei werden aber im  Array auch die weiteren Eigenschaften abgespeichert (im Gegensatz zum Ausgangs-Array).

    XAML:

    <Window x:Class="WpfApp1.Window03"
            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:WpfApp1"
            mc:Ignorable="d"
            Title="Window03" Height="450" Width="800">
      <Window.Resources>
        <local:Window03VM x:Key="vm"/>
      </Window.Resources>
      <Grid DataContext="{StaticResource vm}">
        <Grid.RowDefinitions>
          <RowDefinition Height="Auto"/>
          <RowDefinition/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
          <ColumnDefinition/>
          <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Button Grid.Row="0" Grid.Column="0" Content="Laden" Command="{Binding Cmd}" CommandParameter="Load" Margin="5"/>
        <Button Grid.Row="0" Grid.Column="1" Content="Speichern" Command="{Binding Cmd}" CommandParameter="Save" Margin="5"/>
        <DataGrid Grid.Row="1" Grid.Column="0" ItemsSource="{Binding View1}"/>
        <DataGrid Grid.Row="1" Grid.Column="1" ItemsSource="{Binding View2}"/>
      </Grid>
    </Window>

    Und dazu der weitere Code:

    using Newtonsoft.Json;
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.IO;
    using System.Runtime.CompilerServices;
    using System.Windows;
    using System.Windows.Data;
    using System.Windows.Input;
    
    namespace WpfApp1
    {
      public class Window03VM : INotifyPropertyChanged
      {
    
        public ICommand Cmd { get { return new RelayCommand(CmdExec, CmdCanExec); } }
    
        private void CmdExec(object state)
        {
          switch (state.ToString())
          {
            case "Load":
              cvs1.Source = DataLoader.LoadTestdefinition(@"Window03JSon.txt");
              cvs1.View.CurrentChanged += View_CurrentChanged;
              cvs1.View.MoveCurrentTo(null);
              OnPropertyChanged(nameof(View1));
              break;
            case "Save":
              DataLoader.SaveTestdefinition((List<Testdefinition>)cvs1.Source, @"Window03JSon_out.txt");
              break;
            default:
              MessageBox.Show("nicht unterstützt");
              break;
          }
        }
    
        private bool CmdCanExec(object state)
        {
          switch (state.ToString())
          {
            case "Save":
              return cvs1.Source != null;
            default:
              return true;
          }
        }
    
        CollectionViewSource cvs1 = new CollectionViewSource();
        public ICollectionView View1 { get { return cvs1.View; } }
    
        CollectionViewSource cvs2 = new CollectionViewSource();
        public ICollectionView View2 { get { return cvs2.View; } }
    
        private void View_CurrentChanged(object sender, EventArgs e)
        {
          cvs2.Source = ((Testdefinition)((ICollectionView)sender).CurrentItem)?.TestSteps;
          OnPropertyChanged(nameof(View2));
        }
    
        #region  OnPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged([CallerMemberName] string propName = "") =>
          PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
        #endregion
    
        public class Testdefinition
        {
          // properties of TestDefinition
          [JsonProperty("TestID")]
          public int TestID { get; set; }
    
          [JsonProperty("TestVersion")]
          public double TestVersion { get; set; }
    
          [JsonProperty("TestGroup")]
          public string TestGroup { get; set; }
    
          [JsonProperty("TestName")]
          public string TestName { get; set; }
    
          [JsonProperty("Result")]
          public string Result { get; set; }
    
          [JsonProperty("Comment")]
          public string Comment { get; set; }
    
          [JsonProperty("TestSteps")]
          public string[] StepArray { get; set; }
    
          [JsonProperty("none")]
          public List<TestStep> TestSteps
          {
            get
            {
              List<TestStep> s = new List<TestStep>();
              for (int i = 0; i < StepArray.Length; i++) s.Add(new TestStep() { StepDescription = StepArray[i] });
              return s;
            }
          }
        }
    
        public class TestStep
        {
          public string StepDescription { get; set; }
          public bool Passed { get; set; } = false;
          public bool Failed { get; set; } = false;
          public bool Skipped { get; set; } = false;
          public string Comment { get; set; }
        }
    
        public class DataLoader
        {
          public static List<Testdefinition> LoadTestdefinition(string FileName)
          {
            //reads the file from the open file dialog
            StreamReader Test = new StreamReader(FileName);
            // deserializes the file in to a string
            var instances = JsonConvert.DeserializeObject<List<Testdefinition>>(Test.ReadToEnd());
            return instances;
          }
          public static void SaveTestdefinition(List<Testdefinition> instances, string FileName)
          {
            //reads the file from the open file dialog
            using (StreamWriter Test = new StreamWriter(FileName))
            {
              // deserializes the file in to a string
              Test.Write(JsonConvert.SerializeObject(instances));
            }
          }
        }
      }
    }
    


    --
    Viele Grüsse / Best Regards
    Peter Fleischer (former MVP for Developer Technologies)
    Homepage, Tipps, Tricks

    Samstag, 9. März 2019 07:52
  • Hallo Peter,

    danke für deinen Denkanstoß. Hab es jetzt sowiet das auch wenn man im oberen DG die Zeile (TestId) wechselt ,die Werte und die Checkboxen zwischengespeichert werden.
    Nun hänge ich an dem Problem wie ich die beiden DataGrids auslese und wieder als JSON Datei auf der lokalen Platte speichere.
    Das Problem liegt nicht daran es als JSON Datei zu speichern, sondern da ran das ich an die Daten im DataGrid irgendwie nicht dran komme.
    Und auch wie ich beide DG´s azugleich auslese und dann einen einzigen String draus bastle, ist mir grade auch noch ein Rätsel.
    Vieleicht hast du da einen Tip wie sich das am elgantesten lösen läßt
    Danke

    Viele Grüße

    Freitag, 15. März 2019 12:25
  • Hi,
    in dem von mir geposteten Beispiel ist doch das Speichern der Daten aus den DataGrid enthalten. Wo hast Du da Probleme?

    Lege ein neues WPF-Projekt an, kopiere den Code in den XAML des Window, lege eine class-Datei an und kopiere den Programmcode dort hinein, passe die Pfade mit den Dateinamen an Deine Umgebung an und füge dem Projekt noch die Relay-Klasse hinzu. Und schon kann es losgehen. 1. Button lädt und zeigt an, 2. Button speichert alles.


    --
    Viele Grüsse / Best Regards
    Peter Fleischer (former MVP for Developer Technologies)
    Homepage, Tipps, Tricks

    Freitag, 15. März 2019 13:10
  • Es werden nur die angezeigten Daten gespeichert jedoch nicht die veränderten.
    Genau daran leigt es im Moment.

    Auch wurden die boolschen Werte immer wenn man eine neue Zeile in DataGrid1
    angklickt und bearbeitet hat überschrieben und nicht gespeichert.
    Das dies nun zwischengespeichert wird hab ich hinbekommmen.
    Genau um diese geänderten Werte/Daten geht es nun .
    Diese sollen aus den DataGrid´s raus in ein JSON File geschrieben werden.
    Da lauf ich im Moment von einer exeption zur nächsten.

    Grüße

    Freitag, 15. März 2019 13:27
  • Hi,
    mein Beispiel ist nicht ganz vollständig. Da ist noch etwas Konzeptionelles zu tun.

    Dein Ausgangs-JSON hat für die TestSteps ein String-Array. Dein TestStep ist aber eine Klasse mit mehreren Eigenschaften. Die Frage stellt sich jetzt, wie soll das String-Array in die TestStep-Klassen transformiert werden.

    Ein weiteres Problem ist das Hinzufügen von Einträgen. Wenn das möglich sein soll, dann ist zu klären, wie mit dem String-Array zu verfahren ist. Ein Array muss bei der Neuanlage dimensioniert werden.

    Wenn das alles geklärt ist, dann Kann man eine dementsprechend funktionierende Lösung erstellen.

    Nutze mal im Beispiel diese Version der Klasse Testdefinition und da werden auch die geänderten booleaschen Werte und TestSteps-Neu abgelegt.

        public class Testdefinition
        {
          // properties of TestDefinition
          [JsonProperty("TestID")]
          public int TestID { get; set; }
    
          [JsonProperty("TestVersion")]
          public double TestVersion { get; set; }
    
          [JsonProperty("TestGroup")]
          public string TestGroup { get; set; }
    
          [JsonProperty("TestName")]
          public string TestName { get; set; }
    
          [JsonProperty("Result")]
          public string Result { get; set; }
    
          [JsonProperty("Comment")]
          public string Comment { get; set; }
    
          [JsonProperty("TestSteps")]
          public string[] StepArray { get; set; }
    
          private List<TestStep> _testSteps = new List<TestStep>();
          [JsonProperty("TestSteps_Neu")]
          public List<TestStep> TestSteps
          {
            get
            {
              if (this._testSteps.Count < this.StepArray.Length)
              for (int i = 0; i < StepArray.Length; i++) this._testSteps.Add(new TestStep() { StepDescription = StepArray[i] });
              return this._testSteps;
            }
          }
        }


    --
    Viele Grüsse / Best Regards
    Peter Fleischer (former MVP for Developer Technologies)
    Homepage, Tipps, Tricks



    Freitag, 15. März 2019 14:27
  • Hallo,

    wäre es nicht grundlegend etwas einfacher wenn man das ganze in eine Liste verpackt?
    Code wie du ihn hier als letztes gepostet hast hab ich für das zweite DataGrid verwendet um hier nur die boolschen Werte abzulegen und diese bei Änderung auch zu behalten.

    Montag, 18. März 2019 10:01
  • Hi,
    in Deinem Ausgangsposting hast Du eine JSon-Schnittstelle mit Array als Ausgangszustand genannt, die in einem zweiten DataGrid darzustellen ist. Wenn Du etwas anderes bekommst, z.B. eine Liste mit Objekten, dann ist das eine andere Fragestellung. Hast Du denn meinen Code mal ausprobiert? Als Ausgabe habe ich die Liste der TestStep-Objekte ausgegeben.

    --
    Viele Grüsse / Best Regards
    Peter Fleischer (former MVP for Developer Technologies)
    Homepage, Tipps, Tricks

    Montag, 18. März 2019 12:39