none
How do you deal with DataSet in MVVM?

    Question

  • Since DataSet is somehow a first-class binding source, is there a need to wrap the DataTable into an Object Model? DataTable is already a model representation on its own, do you just need the ViewModel?
    Friday, April 24, 2009 7:50 PM

Answers

  • You can convert DataTable (DataSet is constructed by one or more DataTables) into ObservableCollection and then bind ObservableCollection to UI element.

    For example:

    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>
            <Button Canvas.Left="198" Canvas.Top="12" Height="23" Name="btnAddData" Width="75" Click="btnAddData_Click">Add Data</Button>
        </Canvas>
    </Window>
    

    C#
    using System;
    using System.Collections.Generic;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Collections.ObjectModel;
    using System.Data;
    using System.Threading;
    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
                Random r = new Random();
                for (int i = 1; i <= 10; i++)
                {
                    for (int n = 1; n <= 5; n++)
                    {
                        for (int j = 0; j < 30; j++)
                        {
                            Thread.Sleep(1); 
                            int randomDay = r.Next(30) + 1;
                            AddRow(i  , n, randomDay, 1);
                        }
                    }
                }
                #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)
            {
                RefreshData();
            }
            public void RefreshData()
            {
                //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 ProjectID= ProjectIDList[i];
                        //Get WorkRecord
                        int[] MyWorkRecord = GetWorkRecord(dt, ProjectID);
                        ProjectWorkHours newProjectWorkHours = 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);
                    }
                }
            }
            private void btnAddData_Click(object sender, RoutedEventArgs e)
            {
                Random r = new Random();
                for (int i = 0; i < 4; i++)
                {
                    int randomPro = r.Next(4) + 1;
                    int randomDay = r.Next(30)+1;
                    AddRow(i+1, randomPro, randomDay, 1);
                }
                RefreshData();
            }
        }
        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;
            }
        }
    }
    • Proposed as answer by Tao Liang Monday, April 27, 2009 7:07 AM
    • Marked as answer by JRQ Tuesday, April 28, 2009 9:18 PM
    Monday, April 27, 2009 7:06 AM

All replies

  • You can convert DataTable (DataSet is constructed by one or more DataTables) into ObservableCollection and then bind ObservableCollection to UI element.

    For example:

    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>
            <Button Canvas.Left="198" Canvas.Top="12" Height="23" Name="btnAddData" Width="75" Click="btnAddData_Click">Add Data</Button>
        </Canvas>
    </Window>
    

    C#
    using System;
    using System.Collections.Generic;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Collections.ObjectModel;
    using System.Data;
    using System.Threading;
    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
                Random r = new Random();
                for (int i = 1; i <= 10; i++)
                {
                    for (int n = 1; n <= 5; n++)
                    {
                        for (int j = 0; j < 30; j++)
                        {
                            Thread.Sleep(1); 
                            int randomDay = r.Next(30) + 1;
                            AddRow(i  , n, randomDay, 1);
                        }
                    }
                }
                #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)
            {
                RefreshData();
            }
            public void RefreshData()
            {
                //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 ProjectID= ProjectIDList[i];
                        //Get WorkRecord
                        int[] MyWorkRecord = GetWorkRecord(dt, ProjectID);
                        ProjectWorkHours newProjectWorkHours = 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);
                    }
                }
            }
            private void btnAddData_Click(object sender, RoutedEventArgs e)
            {
                Random r = new Random();
                for (int i = 0; i < 4; i++)
                {
                    int randomPro = r.Next(4) + 1;
                    int randomDay = r.Next(30)+1;
                    AddRow(i+1, randomPro, randomDay, 1);
                }
                RefreshData();
            }
        }
        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;
            }
        }
    }
    • Proposed as answer by Tao Liang Monday, April 27, 2009 7:07 AM
    • Marked as answer by JRQ Tuesday, April 28, 2009 9:18 PM
    Monday, April 27, 2009 7:06 AM
  • Thanks for the sample code. So there seems to be no need for an actual Model, just a View-Model.  Is that pretty standard? 
    Monday, April 27, 2009 3:01 PM
  • The DataTable itself is the Model here, isn't it?
    Monday, April 27, 2009 3:36 PM
  • It's a rough Model, but it is a Model. I'm just wondering if it's customary to create a wrapper for the DataTable, or if it is by "need" basis.

    Monday, April 27, 2009 7:56 PM
  • By need. Design patterns are a guide, they aren't set in stone. Besides, M-V-VM is supposed to deal with anything you can think of as a Model, some DataTables from a SQL database is a typical scenario, IMHO.
    Tuesday, April 28, 2009 7:15 AM
  • What if you needed to convert that Observable collection back to a dataset so it could be saved?
    Thursday, July 08, 2010 3:29 PM