none
Building a spreadsheet with WPF / complex 2-axsis table databinding (using a Grid or DataGrid ) RRS feed

  • Question

  • ok folks, i'm having a real hard time describing my problem but nevertheless i will at least try to explain.

    i have to write a user - interface for a primitive project management system. actually do an Excel --> C# WPF/SQL DB Backend migration.

    basically, the UI consists of a table whose x-axsis consists of n-columns where n is the number of days of the current month, meaning that the number of colums is variable (31 for March, 28 for February, ...). each row on the y-axsis represents an actual project. the cell intersecting the x/y axis represents the number of hours spent for this specific project on that given day. i hope that made at least some sense.

    sadly, the spreadsheet -like layout of the UI is not a subject for discussion. i just have to deal with it, no matter what.

    take this as an example:
                                             Project List for User XXXX
                        March 2009
    Project/Day   | 1 | 2 | 3 | 4 | .. | 31 | Total Hours
    Testproject 1 | 0 | 9 | 4 | 7 | .. |  5 |  xxx hours
    Testproject 2 | 1 | 4 | 3 | 9 | .. |    |  yyy hours
    ....

    the DB backend has just 4 columns forming an unique key, those being the user-ID, the project-ID, a date field and a field containing the number of hours.

    basically, what i'm trying to do is to model a 2D spreadsheet in a relational database.
    now, in theory, i somehow would have to bind every single cell to the db-table. if i would decide not to use databinding at all i would have to manually handle every aspect of displaying/updating/inserting/deleting data. i know with WPF conditional binding (ie. if day = 03/17/2009 bind to object xxx), but i haven't come across an example dealing with my problem so far.

    i've found a thread addressing a similar problem here (http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/23af931e-5cd4-498e-aff5-34d30a9a3716/), but IMHO this example just covers displaying data, but not editing or creating new rows?

    even though i'm afraid i don't make much sense if any at this point, i still have to ask you guys if somebody has at least a hint to point me in the right direction of how to handle this?

    thanks in advance,
    Tom

    Tuesday, March 17, 2009 3:41 PM

Answers

  • XAML:
    <Window x:Class="_temple.Window1" 
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"         
            xmlns:local="clr-namespace:_temple" 
            xmlns:sys="clr-namespace:System;assembly=mscorlib" 
        Width="892" Height="612"
        <Canvas  Background="Azure"
            <ComboBox Canvas.Left="60" Canvas.Top="12" Height="23" Name="ddl" Width="120" SelectionChanged="ddl_SelectionChanged"
                <ComboBox.ItemTemplate> 
                    <DataTemplate> 
                        <ComboBoxItem> 
                            <Binding></Binding
                        </ComboBoxItem> 
                    </DataTemplate> 
                </ComboBox.ItemTemplate> 
            </ComboBox> 
            <ListView Canvas.Left="12" Canvas.Top="46" Height="516" Name="MyListView" Width="846" > 
                <ListView.View> 
                    <GridView AllowsColumnReorder="true" > 
                        <GridViewColumn Header="Project"
                            <GridViewColumn.CellTemplate> 
                                <DataTemplate> 
                                    <TextBlock Width="30"
                                        <TextBlock.Text> 
                                       <Binding   Path="Project"></Binding> 
                                            </TextBlock.Text> 
                                    </TextBlock> 
                                </DataTemplate> 
                            </GridViewColumn.CellTemplate> 
                        </GridViewColumn> 
                        <GridViewColumn Width="720" > 
                            <GridViewColumn.HeaderTemplate> 
                                <DataTemplate> 
                                    <StackPanel Name="HeaderContainer" Orientation="Horizontal"
                                        <TextBlock Width="23">1</TextBlock> 
                                        <TextBlock Width="23">2</TextBlock> 
                                        <TextBlock Width="23">3</TextBlock> 
                                        <TextBlock Width="23">4</TextBlock> 
                                        <TextBlock Width="23">5</TextBlock> 
                                        <TextBlock Width="23">6</TextBlock> 
                                        <TextBlock Width="23">7</TextBlock> 
                                        <TextBlock Width="23">8</TextBlock> 
                                        <TextBlock Width="23">9</TextBlock> 
                                        <TextBlock Width="23">10</TextBlock> 
                                        <TextBlock Width="23">11</TextBlock> 
                                        <TextBlock Width="23">12</TextBlock> 
                                        <TextBlock Width="23">13</TextBlock> 
                                        <TextBlock Width="23">14</TextBlock> 
                                        <TextBlock Width="23">15</TextBlock> 
                                        <TextBlock Width="23">16</TextBlock> 
                                        <TextBlock Width="23">17</TextBlock> 
                                        <TextBlock Width="23">18</TextBlock> 
                                        <TextBlock Width="23">19</TextBlock> 
                                        <TextBlock Width="23">20</TextBlock> 
                                        <TextBlock Width="23">21</TextBlock> 
                                        <TextBlock Width="23">22</TextBlock> 
                                        <TextBlock Width="23">23</TextBlock> 
                                        <TextBlock Width="23">24</TextBlock> 
                                        <TextBlock Width="23">25</TextBlock> 
                                        <TextBlock Width="23">26</TextBlock> 
                                        <TextBlock Width="23">27</TextBlock> 
                                        <TextBlock Width="23">28</TextBlock> 
                                        <TextBlock Width="23">29</TextBlock> 
                                        <TextBlock Width="23">30</TextBlock> 
                                        <TextBlock Width="23">31</TextBlock> 
                                    </StackPanel> 
                                </DataTemplate> 
                            </GridViewColumn.HeaderTemplate> 
                            <GridViewColumn.CellTemplate> 
                                <DataTemplate> 
                                    <StackPanel Loaded="MyStackPanel_Loaded"  Name="MyStackPanel"   Orientation="Horizontal"
                                        <StackPanel.Tag> 
                                            <Binding></Binding
                                        </StackPanel.Tag>  
                                    </StackPanel>  
                                </DataTemplate> 
                            </GridViewColumn.CellTemplate> 
                        </GridViewColumn> 
                        <GridViewColumn Header="TotalHours"
                            <GridViewColumn.CellTemplate> 
                                <DataTemplate> 
                                    <TextBlock Width="60"
                                        <TextBlock.Text> 
                                       <Binding   Path="TotalHours"></Binding> 
                                            </TextBlock.Text> 
                                    </TextBlock> 
                                </DataTemplate> 
                            </GridViewColumn.CellTemplate> 
                        </GridViewColumn> 
                    </GridView> 
                </ListView.View> 
            </ListView> 
            <Label Canvas.Left="12" Canvas.Top="12" Height="28"  Width="42">User:</Label> 
        </Canvas> 
    </Window> 
     

    • Marked as answer by TomTom1234 Friday, March 27, 2009 6:24 AM
    Wednesday, March 25, 2009 2:31 AM
  • C#:
    using System; 
    using System.Collections.Generic; 
    using System.Linq; 
    using System.Text; 
    using System.Windows; 
    using System.Windows.Controls; 
    using System.Windows.Data; 
    using System.Windows.Documents; 
    using System.Windows.Input; 
    using System.Windows.Media; 
    using System.Windows.Media.Imaging; 
    using System.Windows.Navigation; 
    using System.Windows.Shapes; 
    using System.Collections.ObjectModel; 
    using System.Data; 
    namespace _temple 
        /// <summary> 
        /// Interaction logic for Window1.xaml 
        /// </summary> 
        public partial class Window1 : Window 
        { 
            public DataTable data = new DataTable(); 
            public DataTable dtBind = new DataTable(); 
            public ObservableCollection<int> UserIDList = new ObservableCollection<int>(); 
            ObservableCollection<ProjectWorkHours> DataList = new ObservableCollection<ProjectWorkHours>(); 
            public Window1() 
            {  
                InitializeComponent(); 
                Display(); 
            } 
            public void Display() 
            { 
                data = new DataTable(); 
                data.Columns.Add("UserID"); 
                data.Columns.Add("ProjectID"); 
                data.Columns.Add("Day"); 
                data.Columns.Add("Number"); 
                //add some data 
                AddData(); 
                //Set Bind 
                dtBind = data.Copy(); 
                ConvertDataTable(dtBind);  
                this.MyListView.ItemsSource = DataList
                //Get all users 
                ResetUserList(data); 
                //Bind UserList to ComboBox 
                ddl.ItemsSource = UserIDList
                ddl.SelectedIndex =0
            } 
            public void AddData() 
            { 
                #region 
                AddRow(1, 1, 2, 1 ); 
                AddRow(1, 1, 1, 1); 
                AddRow(1, 2, 22, 1); 
                AddRow(1, 3, 31, 9);   
                AddRow(1, 2, 5, 1); 
                AddRow(1, 2, 6, 2); 
                AddRow(2, 1, 7, 1); 
                AddRow(2, 3, 8, 1); 
                AddRow(2, 1, 1, 1); 
                AddRow(2, 1, 18, 1); 
                AddRow(2, 3, 9, 1); 
                AddRow(2, 1, 1, 3); 
                AddRow(3, 2, 21, 3); 
                AddRow(3, 1, 11, 1); 
                AddRow(3, 1, 15, 3); 
                AddRow(3, 2, 1, 2); 
                AddRow(3, 1, 9, 1); 
                AddRow(3, 2, 1, 2); 
                AddRow(4, 1, 31, 1); 
                AddRow(4, 2, 1, 1); 
                AddRow(4, 1, 12, 5); 
                AddRow(4, 3, 1, 1); 
                AddRow(4, 1, 21, 1); 
                AddRow(4, 1, 31, 9); 
                #endregion 
            } 
            public void ResetUserList( DataTable dt ) 
            { 
                UserIDList.Clear(); 
                for ( int i = 0 ; i < dt.Rows.Count; i ++ ) 
                { 
                    DataRow dr = dt.Rows[i]; 
                    int UserID = int.Parse( dr["UserID"].ToString() ); 
                    if ( !UserIDList.Contains( UserID ) ) 
                    { 
                        UserIDList.Add( UserID ); 
                    } 
                } 
            } 
            public void AddRow( int _user, int _pro, int _day, int _num ) 
            { 
                DataRow dr = data.NewRow(); 
                dr["UserID"] = _user; 
                dr["ProjectID"] = _pro; 
                dr["Day"] = _day; 
                dr["Number"] = _num; 
                data.Rows.Add(dr); 
            } 
            private void ddl_SelectionChanged(object sender, SelectionChangedEventArgs e) 
            { 
                //Change the dtBind using Select 
                string userid = ddl.SelectedItem.ToString(); 
                DataRow[] drC = data.Select("UserID='" + userid + "'"); 
                dtBind.Rows.Clear(); 
                for (int i = 0; i < drC.Length; i++) 
                { 
                    DataRow dr = dtBind.NewRow(); 
                    DataRow _dr = drC[i];    
                    dr["UserID"] = _dr["UserID"]; 
                    dr["ProjectID"] =_dr["ProjectID"]; 
                    dr["Day"] = _dr["Day"]; 
                    dr["Number"] = _dr["Number"]; 
                    dtBind.Rows.Add(dr); 
                } 
                ConvertDataTable(dtBind); 
                MyListView.ItemsSource = DataList
            }        
            public void ConvertDataTable( DataTable dt ) 
            { 
                DataList  = new ObservableCollection<ProjectWorkHours>(); 
                //Scan and arrange data into ObservableCollection 
                int UserID = 0
                if ( dt.Rows.Count >0 ) 
                { 
                    UserID = int.Parse( dt.Rows[0]["UserID"].ToString() ); 
                    //Distill project id list 
                    List<int> ProjectIDList = GetProjectIDList( dt ); 
                    for ( int i = 0 ; i < ProjectIDList.Count; i ++ ) 
                    { 
                        int ProjectIDProjectIDList[i]; 
                        //Get WorkRecord 
                        int[] MyWorkRecord = GetWorkRecord(dt, ProjectID); 
                        ProjectWorkHours newnewProjectWorkHours = new ProjectWorkHours(UserID,ProjectID,MyWorkRecord); 
                        DataList.Add( newProjectWorkHours); 
                    }            
                }  
            } 
            public List<int> GetProjectIDList( DataTable dt ) 
            { 
                List<int> ProjectIDList = new List<int>(); 
                for ( int i = 0 ; i < dt.Rows.Count; i ++ ) 
                { 
                    DataRow dr = dt.Rows[i]; 
                    int ProjectID = int.Parse( dr["ProjectID"].ToString() ); 
                    if ( !ProjectIDList.Contains( ProjectID ) ) 
                    { 
                        ProjectIDList.Add(ProjectID); 
                    } 
                } 
                return ProjectIDList; 
            } 
            public int[] GetWorkRecord( DataTable dt, int ProjectID ) 
            { 
                int[] MyWorkRecord = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 
                //scan the data 
                DataRow[]  drScan = dt.Select( " ProjectID='"+ProjectID+"' " ); 
                for (int i = 0; i < drScan.Length; i++) 
                { 
                    DataRow dr = drScan[i]; 
                    int day = int.Parse( dr["Day"].ToString() ); 
                    int num = int.Parse( dr["Number"].ToString() ); 
                    MyWorkRecord[day-1] += num; 
                } 
                return MyWorkRecord; 
            } 
            private void MyStackPanel_Loaded(object sender, RoutedEventArgs e) 
            { 
                StackPanel MyStackPanel = sender as StackPanel; 
                if (MyStackPanel != null) 
                { 
                    MyStackPanel.Children.Clear(); 
                    for (int i = 1; i <= 31; i++) 
                    { 
                        TextBox txt = new TextBox(); 
                        txt.Width = 23
                        ProjectWorkHours PW = MyStackPanel.Tag as ProjectWorkHours; 
                        if (PW != null) 
                        { 
                            txt.Text = PW.WorkRecord[i - 1].ToString(); 
                        } 
                        MyStackPanel.Children.Add(txt); 
                    } 
                } 
            } 
        } 
        public class ProjectWorkHours 
        { 
            public int User { set; get; } 
            public int Project {set;get;} 
            public int[] WorkRecord {set;get;} 
            public int TotalHours{set;get;} 
            public ProjectWorkHours( int _user, int _proj, int[] _work ) 
            { 
                User = _user
                Project = _proj
                WorkRecord = _work
                TotalHours = SumTotal( _work ); 
            } 
            public int SumTotal( int[] number ) 
            { 
                int result = 0
                for ( int i = 0 ; i < number.Length; i ++ ) 
                { 
                    result += number[i]; 
                } 
                return result; 
            } 
        } 


    • Marked as answer by TomTom1234 Friday, March 27, 2009 6:24 AM
    Wednesday, March 25, 2009 2:32 AM
  • You should convert DataTable to a kind of data that can be bound directly to UI such as ObservableCollection. In the demo project below the relationship DataTable is converted into ObservableCollection< ProjectWorkHours>. ProjectWorkHours is a class that defines the work record, user, project and total work hours. The TextBox is created in memory dynamically. A ComoBox can control the selection of DataTable.

    Hope it helps.

    • Marked as answer by Tao Liang Wednesday, March 25, 2009 2:31 AM
    Wednesday, March 25, 2009 2:30 AM

All replies

  • i already wrote a functional but very crude prototype by using a grid and manually adding the columns to the ColumnDefinition and manually creating the rows (each row consisting of n textboxes for the hours for every day), and a save button that, when pressed, calls a function which iterates through every single cell and saves changes to the DB via LINQToSQL the fly. even though this is actually working as required its still very inelegant and just crude ... there has to be some better way to do this...
    Tuesday, March 17, 2009 4:33 PM
  • ok. seems i was just lacking the correct terminology. what i basically have to do is to write an editable Pivot table.
     seems i need an DAL / presentation layer model. again, i'd appreciate any hint i can get!
    Wednesday, March 18, 2009 3:14 PM
  • anyone?
    Thursday, March 19, 2009 7:51 PM
  • You should convert DataTable to a kind of data that can be bound directly to UI such as ObservableCollection. In the demo project below the relationship DataTable is converted into ObservableCollection< ProjectWorkHours>. ProjectWorkHours is a class that defines the work record, user, project and total work hours. The TextBox is created in memory dynamically. A ComoBox can control the selection of DataTable.

    Hope it helps.

    • Marked as answer by Tao Liang Wednesday, March 25, 2009 2:31 AM
    Wednesday, March 25, 2009 2:30 AM
  • XAML:
    <Window x:Class="_temple.Window1" 
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"         
            xmlns:local="clr-namespace:_temple" 
            xmlns:sys="clr-namespace:System;assembly=mscorlib" 
        Width="892" Height="612"
        <Canvas  Background="Azure"
            <ComboBox Canvas.Left="60" Canvas.Top="12" Height="23" Name="ddl" Width="120" SelectionChanged="ddl_SelectionChanged"
                <ComboBox.ItemTemplate> 
                    <DataTemplate> 
                        <ComboBoxItem> 
                            <Binding></Binding
                        </ComboBoxItem> 
                    </DataTemplate> 
                </ComboBox.ItemTemplate> 
            </ComboBox> 
            <ListView Canvas.Left="12" Canvas.Top="46" Height="516" Name="MyListView" Width="846" > 
                <ListView.View> 
                    <GridView AllowsColumnReorder="true" > 
                        <GridViewColumn Header="Project"
                            <GridViewColumn.CellTemplate> 
                                <DataTemplate> 
                                    <TextBlock Width="30"
                                        <TextBlock.Text> 
                                       <Binding   Path="Project"></Binding> 
                                            </TextBlock.Text> 
                                    </TextBlock> 
                                </DataTemplate> 
                            </GridViewColumn.CellTemplate> 
                        </GridViewColumn> 
                        <GridViewColumn Width="720" > 
                            <GridViewColumn.HeaderTemplate> 
                                <DataTemplate> 
                                    <StackPanel Name="HeaderContainer" Orientation="Horizontal"
                                        <TextBlock Width="23">1</TextBlock> 
                                        <TextBlock Width="23">2</TextBlock> 
                                        <TextBlock Width="23">3</TextBlock> 
                                        <TextBlock Width="23">4</TextBlock> 
                                        <TextBlock Width="23">5</TextBlock> 
                                        <TextBlock Width="23">6</TextBlock> 
                                        <TextBlock Width="23">7</TextBlock> 
                                        <TextBlock Width="23">8</TextBlock> 
                                        <TextBlock Width="23">9</TextBlock> 
                                        <TextBlock Width="23">10</TextBlock> 
                                        <TextBlock Width="23">11</TextBlock> 
                                        <TextBlock Width="23">12</TextBlock> 
                                        <TextBlock Width="23">13</TextBlock> 
                                        <TextBlock Width="23">14</TextBlock> 
                                        <TextBlock Width="23">15</TextBlock> 
                                        <TextBlock Width="23">16</TextBlock> 
                                        <TextBlock Width="23">17</TextBlock> 
                                        <TextBlock Width="23">18</TextBlock> 
                                        <TextBlock Width="23">19</TextBlock> 
                                        <TextBlock Width="23">20</TextBlock> 
                                        <TextBlock Width="23">21</TextBlock> 
                                        <TextBlock Width="23">22</TextBlock> 
                                        <TextBlock Width="23">23</TextBlock> 
                                        <TextBlock Width="23">24</TextBlock> 
                                        <TextBlock Width="23">25</TextBlock> 
                                        <TextBlock Width="23">26</TextBlock> 
                                        <TextBlock Width="23">27</TextBlock> 
                                        <TextBlock Width="23">28</TextBlock> 
                                        <TextBlock Width="23">29</TextBlock> 
                                        <TextBlock Width="23">30</TextBlock> 
                                        <TextBlock Width="23">31</TextBlock> 
                                    </StackPanel> 
                                </DataTemplate> 
                            </GridViewColumn.HeaderTemplate> 
                            <GridViewColumn.CellTemplate> 
                                <DataTemplate> 
                                    <StackPanel Loaded="MyStackPanel_Loaded"  Name="MyStackPanel"   Orientation="Horizontal"
                                        <StackPanel.Tag> 
                                            <Binding></Binding
                                        </StackPanel.Tag>  
                                    </StackPanel>  
                                </DataTemplate> 
                            </GridViewColumn.CellTemplate> 
                        </GridViewColumn> 
                        <GridViewColumn Header="TotalHours"
                            <GridViewColumn.CellTemplate> 
                                <DataTemplate> 
                                    <TextBlock Width="60"
                                        <TextBlock.Text> 
                                       <Binding   Path="TotalHours"></Binding> 
                                            </TextBlock.Text> 
                                    </TextBlock> 
                                </DataTemplate> 
                            </GridViewColumn.CellTemplate> 
                        </GridViewColumn> 
                    </GridView> 
                </ListView.View> 
            </ListView> 
            <Label Canvas.Left="12" Canvas.Top="12" Height="28"  Width="42">User:</Label> 
        </Canvas> 
    </Window> 
     

    • Marked as answer by TomTom1234 Friday, March 27, 2009 6:24 AM
    Wednesday, March 25, 2009 2:31 AM
  • C#:
    using System; 
    using System.Collections.Generic; 
    using System.Linq; 
    using System.Text; 
    using System.Windows; 
    using System.Windows.Controls; 
    using System.Windows.Data; 
    using System.Windows.Documents; 
    using System.Windows.Input; 
    using System.Windows.Media; 
    using System.Windows.Media.Imaging; 
    using System.Windows.Navigation; 
    using System.Windows.Shapes; 
    using System.Collections.ObjectModel; 
    using System.Data; 
    namespace _temple 
        /// <summary> 
        /// Interaction logic for Window1.xaml 
        /// </summary> 
        public partial class Window1 : Window 
        { 
            public DataTable data = new DataTable(); 
            public DataTable dtBind = new DataTable(); 
            public ObservableCollection<int> UserIDList = new ObservableCollection<int>(); 
            ObservableCollection<ProjectWorkHours> DataList = new ObservableCollection<ProjectWorkHours>(); 
            public Window1() 
            {  
                InitializeComponent(); 
                Display(); 
            } 
            public void Display() 
            { 
                data = new DataTable(); 
                data.Columns.Add("UserID"); 
                data.Columns.Add("ProjectID"); 
                data.Columns.Add("Day"); 
                data.Columns.Add("Number"); 
                //add some data 
                AddData(); 
                //Set Bind 
                dtBind = data.Copy(); 
                ConvertDataTable(dtBind);  
                this.MyListView.ItemsSource = DataList
                //Get all users 
                ResetUserList(data); 
                //Bind UserList to ComboBox 
                ddl.ItemsSource = UserIDList
                ddl.SelectedIndex =0
            } 
            public void AddData() 
            { 
                #region 
                AddRow(1, 1, 2, 1 ); 
                AddRow(1, 1, 1, 1); 
                AddRow(1, 2, 22, 1); 
                AddRow(1, 3, 31, 9);   
                AddRow(1, 2, 5, 1); 
                AddRow(1, 2, 6, 2); 
                AddRow(2, 1, 7, 1); 
                AddRow(2, 3, 8, 1); 
                AddRow(2, 1, 1, 1); 
                AddRow(2, 1, 18, 1); 
                AddRow(2, 3, 9, 1); 
                AddRow(2, 1, 1, 3); 
                AddRow(3, 2, 21, 3); 
                AddRow(3, 1, 11, 1); 
                AddRow(3, 1, 15, 3); 
                AddRow(3, 2, 1, 2); 
                AddRow(3, 1, 9, 1); 
                AddRow(3, 2, 1, 2); 
                AddRow(4, 1, 31, 1); 
                AddRow(4, 2, 1, 1); 
                AddRow(4, 1, 12, 5); 
                AddRow(4, 3, 1, 1); 
                AddRow(4, 1, 21, 1); 
                AddRow(4, 1, 31, 9); 
                #endregion 
            } 
            public void ResetUserList( DataTable dt ) 
            { 
                UserIDList.Clear(); 
                for ( int i = 0 ; i < dt.Rows.Count; i ++ ) 
                { 
                    DataRow dr = dt.Rows[i]; 
                    int UserID = int.Parse( dr["UserID"].ToString() ); 
                    if ( !UserIDList.Contains( UserID ) ) 
                    { 
                        UserIDList.Add( UserID ); 
                    } 
                } 
            } 
            public void AddRow( int _user, int _pro, int _day, int _num ) 
            { 
                DataRow dr = data.NewRow(); 
                dr["UserID"] = _user; 
                dr["ProjectID"] = _pro; 
                dr["Day"] = _day; 
                dr["Number"] = _num; 
                data.Rows.Add(dr); 
            } 
            private void ddl_SelectionChanged(object sender, SelectionChangedEventArgs e) 
            { 
                //Change the dtBind using Select 
                string userid = ddl.SelectedItem.ToString(); 
                DataRow[] drC = data.Select("UserID='" + userid + "'"); 
                dtBind.Rows.Clear(); 
                for (int i = 0; i < drC.Length; i++) 
                { 
                    DataRow dr = dtBind.NewRow(); 
                    DataRow _dr = drC[i];    
                    dr["UserID"] = _dr["UserID"]; 
                    dr["ProjectID"] =_dr["ProjectID"]; 
                    dr["Day"] = _dr["Day"]; 
                    dr["Number"] = _dr["Number"]; 
                    dtBind.Rows.Add(dr); 
                } 
                ConvertDataTable(dtBind); 
                MyListView.ItemsSource = DataList
            }        
            public void ConvertDataTable( DataTable dt ) 
            { 
                DataList  = new ObservableCollection<ProjectWorkHours>(); 
                //Scan and arrange data into ObservableCollection 
                int UserID = 0
                if ( dt.Rows.Count >0 ) 
                { 
                    UserID = int.Parse( dt.Rows[0]["UserID"].ToString() ); 
                    //Distill project id list 
                    List<int> ProjectIDList = GetProjectIDList( dt ); 
                    for ( int i = 0 ; i < ProjectIDList.Count; i ++ ) 
                    { 
                        int ProjectIDProjectIDList[i]; 
                        //Get WorkRecord 
                        int[] MyWorkRecord = GetWorkRecord(dt, ProjectID); 
                        ProjectWorkHours newnewProjectWorkHours = new ProjectWorkHours(UserID,ProjectID,MyWorkRecord); 
                        DataList.Add( newProjectWorkHours); 
                    }            
                }  
            } 
            public List<int> GetProjectIDList( DataTable dt ) 
            { 
                List<int> ProjectIDList = new List<int>(); 
                for ( int i = 0 ; i < dt.Rows.Count; i ++ ) 
                { 
                    DataRow dr = dt.Rows[i]; 
                    int ProjectID = int.Parse( dr["ProjectID"].ToString() ); 
                    if ( !ProjectIDList.Contains( ProjectID ) ) 
                    { 
                        ProjectIDList.Add(ProjectID); 
                    } 
                } 
                return ProjectIDList; 
            } 
            public int[] GetWorkRecord( DataTable dt, int ProjectID ) 
            { 
                int[] MyWorkRecord = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 
                //scan the data 
                DataRow[]  drScan = dt.Select( " ProjectID='"+ProjectID+"' " ); 
                for (int i = 0; i < drScan.Length; i++) 
                { 
                    DataRow dr = drScan[i]; 
                    int day = int.Parse( dr["Day"].ToString() ); 
                    int num = int.Parse( dr["Number"].ToString() ); 
                    MyWorkRecord[day-1] += num; 
                } 
                return MyWorkRecord; 
            } 
            private void MyStackPanel_Loaded(object sender, RoutedEventArgs e) 
            { 
                StackPanel MyStackPanel = sender as StackPanel; 
                if (MyStackPanel != null) 
                { 
                    MyStackPanel.Children.Clear(); 
                    for (int i = 1; i <= 31; i++) 
                    { 
                        TextBox txt = new TextBox(); 
                        txt.Width = 23
                        ProjectWorkHours PW = MyStackPanel.Tag as ProjectWorkHours; 
                        if (PW != null) 
                        { 
                            txt.Text = PW.WorkRecord[i - 1].ToString(); 
                        } 
                        MyStackPanel.Children.Add(txt); 
                    } 
                } 
            } 
        } 
        public class ProjectWorkHours 
        { 
            public int User { set; get; } 
            public int Project {set;get;} 
            public int[] WorkRecord {set;get;} 
            public int TotalHours{set;get;} 
            public ProjectWorkHours( int _user, int _proj, int[] _work ) 
            { 
                User = _user
                Project = _proj
                WorkRecord = _work
                TotalHours = SumTotal( _work ); 
            } 
            public int SumTotal( int[] number ) 
            { 
                int result = 0
                for ( int i = 0 ; i < number.Length; i ++ ) 
                { 
                    result += number[i]; 
                } 
                return result; 
            } 
        } 


    • Marked as answer by TomTom1234 Friday, March 27, 2009 6:24 AM
    Wednesday, March 25, 2009 2:32 AM
  • liangtom,

    thank you so much for your effort!!!! guys like you are what makes this forum great!

    -Tom

    Friday, March 27, 2009 6:26 AM
  • liangtom, i tried to implement your solution and it works like a charm!

    again, thank you VERY MUCH for taking the time to help me out.

    just to make it clear, i'm working for a non-profit NGO, its not like i would make money by using your knowledge. you probably won't care much, but i just wanted to have it said.

    i tried to replace the first column (project-ID) with a databound combobox (that is, i want to display the project human-readable, but still use the ID), but i failed. none of the binding methods (setting ComboBox.DataContext) i tried seem to work :(

    also, i'm having a hard time implementing at least basic CRUD functionality. to me, moving from Winforms to WPF is an exremely exhausting task.
    it seems like WPF is an extremely powerfull concept, much more than WinForms, but at the moment it really seems to lack the enormous ressources Winforms has. with Winforms, it's virtually impossible to encounter a problem that hasn't been answered before, not so with WPF :(

    again, thanks a lot for your help!

    -Tom
    Friday, April 3, 2009 12:12 PM