none
Raggruppamento in datagrid RRS feed

  • Domanda

  • Ciao a tutti,

    Ho una lista che contiene le proprietà Day Start ed End in formato DateTime:

    Start ed End li utilizzo per impostate hh:mm 

    mentre Day nel formato dd-mm/yyyy

    in poche parole sono orari di ingresso>uscita

    la lista può contenere  più di un record con lo stesso giorno ma con orari differenti

    Quello che vorrei ottenere è un Datagrid che  mi incolonna  tutti gli Start/End in seguenza dello stesso giorno

    Ad esempio :

    Day | Start1 | End1 | Start2 | End2 | Start3 | End13 | Start4 | End.4....e così via

    se possibile Start ed End li vorrei mettere nella stessa cella 

    questa cosa riesco a farla solo con 3 colonne...rispettivamente: Day |Start |End

    Qualcuno potrebbe darmi qualche suggerimento ?

    grazie in anticipo a tutti

     


    fabio miceli

    lunedì 27 luglio 2020 15:15

Risposte

  • Ciao, ho appena scritto un piccolo programma (utilizzando Wpf) che potrebbe risolvere il tuo problema:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Media;
    
    namespace TabellaOrari
    {    
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
                DisegnaGriglia();
            }
            
            public class Orario
            {            
                public DateTime Start { get; set; }
                public DateTime End { get; set; }
            }
    
            public void DisegnaGriglia()
            {
    
                //genera una lista di esempio
                List<Orario> elencoOrari = new List<Orario>();
                elencoOrari.Add(new Orario() { Start = Convert.ToDateTime("27-07-2020 06:00:00"), End = Convert.ToDateTime("27-07-2020 12:00:00") });
                elencoOrari.Add(new Orario() { Start = Convert.ToDateTime("27-07-2020 07:00:00"), End = Convert.ToDateTime("27-07-2020 12:00:00") });
                elencoOrari.Add(new Orario() { Start = Convert.ToDateTime("27-07-2020 08:00:00"), End = Convert.ToDateTime("27-07-2020 13:00:00") });
                elencoOrari.Add(new Orario() { Start = Convert.ToDateTime("28-07-2020 09:00:00"), End = Convert.ToDateTime("28-07-2020 10:30:00") });
                elencoOrari.Add(new Orario() { Start = Convert.ToDateTime("28-07-2020 06:30:00"), End = Convert.ToDateTime("28-07-2020 12:40:00") });
                elencoOrari.Add(new Orario() { Start = Convert.ToDateTime("28-07-2020 11:00:00"), End = Convert.ToDateTime("28-07-2020 16:20:00") });
                elencoOrari.Add(new Orario() { Start = Convert.ToDateTime("26-07-2020 09:00:00"), End = Convert.ToDateTime("26-07-2020 10:30:00") });
                elencoOrari.Add(new Orario() { Start = Convert.ToDateTime("26-07-2020 06:30:00"), End = Convert.ToDateTime("26-07-2020 12:40:00") });
                
                List<Orario> orariOrdinati = elencoOrari.OrderBy(c => c.Start).ThenBy(c => c.End).ToList();
    
                //cerca nella lista il massimo numero di colonne
                int maxCol = 0;
                int numCol = 0;
                int maxRighe = 1;
                DateTime primoGiorno = orariOrdinati[0].Start.Date;
                foreach (Orario orario in orariOrdinati)
                {
                    if (orario.Start.Date == primoGiorno)
                        numCol++;
                    else
                    {
                        maxRighe++;
                        if (numCol > maxCol)
                            maxCol = numCol;
                        primoGiorno = orario.Start.Date;
                        numCol = 1;
                    }
                }
                maxCol++;
    
                //crea la griglia, per poi agganciarla alla finestra principale
                Grid griglia = new Grid();
                griglia.Margin = new Thickness(0, 0, 0, 0);
                GridLength largCol = new GridLength(1, GridUnitType.Star);
    
                for (int i=0; i<maxCol; i++)
                    griglia.ColumnDefinitions.Add(new ColumnDefinition() { Width = largCol });
    
                for (int i=0; i<maxRighe; i++)
                    griglia.RowDefinitions.Add(new RowDefinition() { Height = largCol });
                
                griglia.ShowGridLines = true;
                            
                primoGiorno = DateTime.MinValue;
                numCol = 0;
                int numRighe = -1;
                foreach (Orario orario in orariOrdinati)
                {                
                    //va a capo se cambia il giorno
                    if (orario.Start.Date > primoGiorno)
                    {
                        primoGiorno = orario.Start.Date;
                        numRighe++;
                        numCol = 0;                    
                    }
                    
                    if (numCol == 0)
                    {
                        //scrive la data nella prima colonna
                        TextBlock scritta1 = new TextBlock();
                        scritta1.FontFamily = new FontFamily("Arial");
                        scritta1.FontSize = 18;
                        scritta1.Text = orario.Start.Date.ToShortDateString();
                        scritta1.Margin = new Thickness(5, 5, 5, 5);
                        scritta1.HorizontalAlignment = HorizontalAlignment.Center;
                        scritta1.VerticalAlignment = VerticalAlignment.Center;
                        Grid.SetColumn(scritta1, numCol++);
                        Grid.SetRow(scritta1, numRighe);
                        griglia.Children.Add(scritta1);
                    }
    
                    //scrive ore Start - End
                    TextBlock scritta2 = new TextBlock();
                    scritta2.FontFamily = new FontFamily("Arial");
                    scritta2.FontSize = 18;
                    scritta2.Text = orario.Start.ToShortTimeString() + " - " + orario.End.ToShortTimeString();
                    scritta2.Margin = new Thickness(5, 5, 5, 5);
                    scritta2.HorizontalAlignment = HorizontalAlignment.Center;
                    scritta2.VerticalAlignment = VerticalAlignment.Center;
                    Grid.SetColumn(scritta2, numCol++);
                    Grid.SetRow(scritta2, numRighe);
                    griglia.Children.Add(scritta2);
                }
    
                //mette la griglia nella finestra principale
                Window finestra = (MainWindow)Application.Current.MainWindow;
                finestra.Height = maxRighe*50;
                finestra.Content = griglia;
                finestra.ShowDialog();
            }
        }
    }
    

    • Contrassegnato come risposta Fabio Miceli martedì 4 agosto 2020 14:00
    martedì 28 luglio 2020 19:04
  • Ah ok, se vuoi utilizzare una Datagrid con il binding di date e orari, facciamo così:

    prima nello xaml (per semplicità nella finestra principale):

    <Window x:Class="TabellaOrari2__DataGrid_.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:TabellaOrari2__DataGrid_"
            mc:Ignorable="d"
            Title="MainWindow" Height="300" Width="400">
        <Grid>
            <DataGrid Name="tabellaOrari" AutoGenerateColumns="False">
                <DataGrid.Columns>
                    <DataGridTextColumn Header="Data" Binding="{Binding Giorno}" />
                </DataGrid.Columns>
                <DataGrid.RowDetailsTemplate>
                    <DataTemplate>
                        <TextBlock Text="Esempio" Margin="10" />
                    </DataTemplate>
                </DataGrid.RowDetailsTemplate>
            </DataGrid>
        </Grid>
    </Window>

    poi nel programma:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    
    namespace TabellaOrari2__DataGrid_
    {
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
                DisegnaGriglia();
            }
    
            public class Orario
            {
                public DateTime Start { get; set; }
                public DateTime End { get; set; }
            }
            
            public class RigaOrario
            {
                public string Giorno { get; set; }
                public string[] InizioFine { get; set; }
    
                public RigaOrario(int maxCol)
                {
                    InizioFine = new string[maxCol - 1];                
                }
            }
    
            public void DisegnaGriglia()
            {
    
                //genera una lista di esempio
                List<Orario> elencoOrari = new List<Orario>();
                elencoOrari.Add(new Orario() { Start = Convert.ToDateTime("27-07-2020 06:00:00"), End = Convert.ToDateTime("27-07-2020 12:00:00") });
                elencoOrari.Add(new Orario() { Start = Convert.ToDateTime("27-07-2020 07:00:00"), End = Convert.ToDateTime("27-07-2020 12:00:00") });
                elencoOrari.Add(new Orario() { Start = Convert.ToDateTime("27-07-2020 08:00:00"), End = Convert.ToDateTime("27-07-2020 13:00:00") });
                elencoOrari.Add(new Orario() { Start = Convert.ToDateTime("28-07-2020 09:00:00"), End = Convert.ToDateTime("28-07-2020 10:30:00") });
                elencoOrari.Add(new Orario() { Start = Convert.ToDateTime("28-07-2020 06:30:00"), End = Convert.ToDateTime("28-07-2020 12:40:00") });
                elencoOrari.Add(new Orario() { Start = Convert.ToDateTime("28-07-2020 11:00:00"), End = Convert.ToDateTime("28-07-2020 16:20:00") });
                elencoOrari.Add(new Orario() { Start = Convert.ToDateTime("26-07-2020 09:00:00"), End = Convert.ToDateTime("26-07-2020 10:30:00") });
                elencoOrari.Add(new Orario() { Start = Convert.ToDateTime("26-07-2020 06:30:00"), End = Convert.ToDateTime("26-07-2020 12:40:00") });
    
                List<Orario> orariOrdinati = elencoOrari.OrderBy(c => c.Start).ThenBy(c => c.End).ToList();
    
                //cerca nella lista il massimo numero di colonne
                int maxCol = 0;
                int numCol = 0;            
                DateTime giornoAttuale = orariOrdinati[0].Start.Date;
                foreach (Orario orario in orariOrdinati)
                {
                    if (orario.Start.Date == giornoAttuale)
                        numCol++;
                    else
                    {                    
                        if (numCol > maxCol)
                            maxCol = numCol;
                        giornoAttuale = orario.Start.Date;
                        numCol = 1;
                    }
                }
                maxCol++;
    
                List<RigaOrario> tabDataGrid = new List<RigaOrario>();
    
                RigaOrario riga = new RigaOrario(maxCol);                        
                
                giornoAttuale = DateTime.MinValue;
                foreach (Orario orario in orariOrdinati)
                {                
                    //se cambia il giorno
                    if (orario.Start.Date > giornoAttuale)
                    {
                        //e non è il primo, aggiunge la riga (precedente già creata)
                        if (giornoAttuale > DateTime.MinValue)
                            tabDataGrid.Add(riga);
    
                        //in tutti i casi crea una nuova riga
                        giornoAttuale = orario.Start.Date;                
                        numCol = 0;
                        riga = new RigaOrario(maxCol);
                        riga.Giorno = orario.Start.Date.ToShortDateString();                    
                    }
                    riga.InizioFine[numCol++] = orario.Start.ToShortTimeString() + " - " + orario.End.ToShortTimeString();
                }            
                tabDataGrid.Add(riga);  //aggiunge l'ultima riga creata
                                        
                //aggiunge alla DataGrid i DataGridTextColumn corrispondenti ai vari orari
                for (int i=0; i<maxCol-1; i++)
                {
                    DataGridTextColumn colonna = new DataGridTextColumn();
                    colonna.Header = $"Inizio-Fine({i})";
                    colonna.Binding = new Binding($"InizioFine[{i}]");
                    tabellaOrari.Columns.Add(colonna);                
                }
                tabellaOrari.ItemsSource = tabDataGrid;                                   
            }
        }
    }
    

    Adesso, credo che ci siamo (DataGrid.RowDetailsTemplate compreso)...


    • Modificato fabiocaruso sabato 1 agosto 2020 05:28
    • Contrassegnato come risposta Fabio Miceli martedì 4 agosto 2020 13:59
    venerdì 31 luglio 2020 18:13

Tutte le risposte

  • Ciao, ho appena scritto un piccolo programma (utilizzando Wpf) che potrebbe risolvere il tuo problema:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Media;
    
    namespace TabellaOrari
    {    
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
                DisegnaGriglia();
            }
            
            public class Orario
            {            
                public DateTime Start { get; set; }
                public DateTime End { get; set; }
            }
    
            public void DisegnaGriglia()
            {
    
                //genera una lista di esempio
                List<Orario> elencoOrari = new List<Orario>();
                elencoOrari.Add(new Orario() { Start = Convert.ToDateTime("27-07-2020 06:00:00"), End = Convert.ToDateTime("27-07-2020 12:00:00") });
                elencoOrari.Add(new Orario() { Start = Convert.ToDateTime("27-07-2020 07:00:00"), End = Convert.ToDateTime("27-07-2020 12:00:00") });
                elencoOrari.Add(new Orario() { Start = Convert.ToDateTime("27-07-2020 08:00:00"), End = Convert.ToDateTime("27-07-2020 13:00:00") });
                elencoOrari.Add(new Orario() { Start = Convert.ToDateTime("28-07-2020 09:00:00"), End = Convert.ToDateTime("28-07-2020 10:30:00") });
                elencoOrari.Add(new Orario() { Start = Convert.ToDateTime("28-07-2020 06:30:00"), End = Convert.ToDateTime("28-07-2020 12:40:00") });
                elencoOrari.Add(new Orario() { Start = Convert.ToDateTime("28-07-2020 11:00:00"), End = Convert.ToDateTime("28-07-2020 16:20:00") });
                elencoOrari.Add(new Orario() { Start = Convert.ToDateTime("26-07-2020 09:00:00"), End = Convert.ToDateTime("26-07-2020 10:30:00") });
                elencoOrari.Add(new Orario() { Start = Convert.ToDateTime("26-07-2020 06:30:00"), End = Convert.ToDateTime("26-07-2020 12:40:00") });
                
                List<Orario> orariOrdinati = elencoOrari.OrderBy(c => c.Start).ThenBy(c => c.End).ToList();
    
                //cerca nella lista il massimo numero di colonne
                int maxCol = 0;
                int numCol = 0;
                int maxRighe = 1;
                DateTime primoGiorno = orariOrdinati[0].Start.Date;
                foreach (Orario orario in orariOrdinati)
                {
                    if (orario.Start.Date == primoGiorno)
                        numCol++;
                    else
                    {
                        maxRighe++;
                        if (numCol > maxCol)
                            maxCol = numCol;
                        primoGiorno = orario.Start.Date;
                        numCol = 1;
                    }
                }
                maxCol++;
    
                //crea la griglia, per poi agganciarla alla finestra principale
                Grid griglia = new Grid();
                griglia.Margin = new Thickness(0, 0, 0, 0);
                GridLength largCol = new GridLength(1, GridUnitType.Star);
    
                for (int i=0; i<maxCol; i++)
                    griglia.ColumnDefinitions.Add(new ColumnDefinition() { Width = largCol });
    
                for (int i=0; i<maxRighe; i++)
                    griglia.RowDefinitions.Add(new RowDefinition() { Height = largCol });
                
                griglia.ShowGridLines = true;
                            
                primoGiorno = DateTime.MinValue;
                numCol = 0;
                int numRighe = -1;
                foreach (Orario orario in orariOrdinati)
                {                
                    //va a capo se cambia il giorno
                    if (orario.Start.Date > primoGiorno)
                    {
                        primoGiorno = orario.Start.Date;
                        numRighe++;
                        numCol = 0;                    
                    }
                    
                    if (numCol == 0)
                    {
                        //scrive la data nella prima colonna
                        TextBlock scritta1 = new TextBlock();
                        scritta1.FontFamily = new FontFamily("Arial");
                        scritta1.FontSize = 18;
                        scritta1.Text = orario.Start.Date.ToShortDateString();
                        scritta1.Margin = new Thickness(5, 5, 5, 5);
                        scritta1.HorizontalAlignment = HorizontalAlignment.Center;
                        scritta1.VerticalAlignment = VerticalAlignment.Center;
                        Grid.SetColumn(scritta1, numCol++);
                        Grid.SetRow(scritta1, numRighe);
                        griglia.Children.Add(scritta1);
                    }
    
                    //scrive ore Start - End
                    TextBlock scritta2 = new TextBlock();
                    scritta2.FontFamily = new FontFamily("Arial");
                    scritta2.FontSize = 18;
                    scritta2.Text = orario.Start.ToShortTimeString() + " - " + orario.End.ToShortTimeString();
                    scritta2.Margin = new Thickness(5, 5, 5, 5);
                    scritta2.HorizontalAlignment = HorizontalAlignment.Center;
                    scritta2.VerticalAlignment = VerticalAlignment.Center;
                    Grid.SetColumn(scritta2, numCol++);
                    Grid.SetRow(scritta2, numRighe);
                    griglia.Children.Add(scritta2);
                }
    
                //mette la griglia nella finestra principale
                Window finestra = (MainWindow)Application.Current.MainWindow;
                finestra.Height = maxRighe*50;
                finestra.Content = griglia;
                finestra.ShowDialog();
            }
        }
    }
    

    • Contrassegnato come risposta Fabio Miceli martedì 4 agosto 2020 14:00
    martedì 28 luglio 2020 19:04
  • Ciao fabiocaruso,

    grazie infinite per l'esempio, si è  esattamente ciò che volevo ottenere :)

    adesso devo mettere tutto dentro un Datagrid.

    Domanda: e possibile in questo caso in DataGrid utilizzare RowDetailsTemplate ??


    fabio miceli

    • Contrassegnato come risposta Fabio Miceli martedì 4 agosto 2020 14:00
    • Contrassegno come risposta annullato Fabio Miceli martedì 4 agosto 2020 14:00
    martedì 28 luglio 2020 20:10
  • Ah ok, se vuoi utilizzare una Datagrid con il binding di date e orari, facciamo così:

    prima nello xaml (per semplicità nella finestra principale):

    <Window x:Class="TabellaOrari2__DataGrid_.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:TabellaOrari2__DataGrid_"
            mc:Ignorable="d"
            Title="MainWindow" Height="300" Width="400">
        <Grid>
            <DataGrid Name="tabellaOrari" AutoGenerateColumns="False">
                <DataGrid.Columns>
                    <DataGridTextColumn Header="Data" Binding="{Binding Giorno}" />
                </DataGrid.Columns>
                <DataGrid.RowDetailsTemplate>
                    <DataTemplate>
                        <TextBlock Text="Esempio" Margin="10" />
                    </DataTemplate>
                </DataGrid.RowDetailsTemplate>
            </DataGrid>
        </Grid>
    </Window>

    poi nel programma:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    
    namespace TabellaOrari2__DataGrid_
    {
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
                DisegnaGriglia();
            }
    
            public class Orario
            {
                public DateTime Start { get; set; }
                public DateTime End { get; set; }
            }
            
            public class RigaOrario
            {
                public string Giorno { get; set; }
                public string[] InizioFine { get; set; }
    
                public RigaOrario(int maxCol)
                {
                    InizioFine = new string[maxCol - 1];                
                }
            }
    
            public void DisegnaGriglia()
            {
    
                //genera una lista di esempio
                List<Orario> elencoOrari = new List<Orario>();
                elencoOrari.Add(new Orario() { Start = Convert.ToDateTime("27-07-2020 06:00:00"), End = Convert.ToDateTime("27-07-2020 12:00:00") });
                elencoOrari.Add(new Orario() { Start = Convert.ToDateTime("27-07-2020 07:00:00"), End = Convert.ToDateTime("27-07-2020 12:00:00") });
                elencoOrari.Add(new Orario() { Start = Convert.ToDateTime("27-07-2020 08:00:00"), End = Convert.ToDateTime("27-07-2020 13:00:00") });
                elencoOrari.Add(new Orario() { Start = Convert.ToDateTime("28-07-2020 09:00:00"), End = Convert.ToDateTime("28-07-2020 10:30:00") });
                elencoOrari.Add(new Orario() { Start = Convert.ToDateTime("28-07-2020 06:30:00"), End = Convert.ToDateTime("28-07-2020 12:40:00") });
                elencoOrari.Add(new Orario() { Start = Convert.ToDateTime("28-07-2020 11:00:00"), End = Convert.ToDateTime("28-07-2020 16:20:00") });
                elencoOrari.Add(new Orario() { Start = Convert.ToDateTime("26-07-2020 09:00:00"), End = Convert.ToDateTime("26-07-2020 10:30:00") });
                elencoOrari.Add(new Orario() { Start = Convert.ToDateTime("26-07-2020 06:30:00"), End = Convert.ToDateTime("26-07-2020 12:40:00") });
    
                List<Orario> orariOrdinati = elencoOrari.OrderBy(c => c.Start).ThenBy(c => c.End).ToList();
    
                //cerca nella lista il massimo numero di colonne
                int maxCol = 0;
                int numCol = 0;            
                DateTime giornoAttuale = orariOrdinati[0].Start.Date;
                foreach (Orario orario in orariOrdinati)
                {
                    if (orario.Start.Date == giornoAttuale)
                        numCol++;
                    else
                    {                    
                        if (numCol > maxCol)
                            maxCol = numCol;
                        giornoAttuale = orario.Start.Date;
                        numCol = 1;
                    }
                }
                maxCol++;
    
                List<RigaOrario> tabDataGrid = new List<RigaOrario>();
    
                RigaOrario riga = new RigaOrario(maxCol);                        
                
                giornoAttuale = DateTime.MinValue;
                foreach (Orario orario in orariOrdinati)
                {                
                    //se cambia il giorno
                    if (orario.Start.Date > giornoAttuale)
                    {
                        //e non è il primo, aggiunge la riga (precedente già creata)
                        if (giornoAttuale > DateTime.MinValue)
                            tabDataGrid.Add(riga);
    
                        //in tutti i casi crea una nuova riga
                        giornoAttuale = orario.Start.Date;                
                        numCol = 0;
                        riga = new RigaOrario(maxCol);
                        riga.Giorno = orario.Start.Date.ToShortDateString();                    
                    }
                    riga.InizioFine[numCol++] = orario.Start.ToShortTimeString() + " - " + orario.End.ToShortTimeString();
                }            
                tabDataGrid.Add(riga);  //aggiunge l'ultima riga creata
                                        
                //aggiunge alla DataGrid i DataGridTextColumn corrispondenti ai vari orari
                for (int i=0; i<maxCol-1; i++)
                {
                    DataGridTextColumn colonna = new DataGridTextColumn();
                    colonna.Header = $"Inizio-Fine({i})";
                    colonna.Binding = new Binding($"InizioFine[{i}]");
                    tabellaOrari.Columns.Add(colonna);                
                }
                tabellaOrari.ItemsSource = tabDataGrid;                                   
            }
        }
    }
    

    Adesso, credo che ci siamo (DataGrid.RowDetailsTemplate compreso)...


    • Modificato fabiocaruso sabato 1 agosto 2020 05:28
    • Contrassegnato come risposta Fabio Miceli martedì 4 agosto 2020 13:59
    venerdì 31 luglio 2020 18:13
  • Ciao Fabio,

    non so come ringraziarti.

    è perfettamente quello che volevo ottenere.

    Grazie infinite

    ciao


    fabio miceli

    lunedì 3 agosto 2020 18:35