Wednesday, 11 August 2010

WPF DataTable with custom column header

<Window x:Class="WpfTable.Window2"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    DataContext="{Binding RelativeSource={RelativeSource Self}}"
    Title="WPF Tables" Height="309" Width="524">
    
    <Window.Resources>
        <DataTemplate x:Key="OverwriteHeaderTemplate">
            <StackPanel>
                <TextBlock Grid.Column="0" Grid.Row="0" HorizontalAlignment="Center" Text="{Binding Path=ColumnName}"/>
                <TextBox x:Name="overwriteText" Grid.Column="0" Grid.Row="1" Text="{Binding Path=OverwriteText}" MinWidth="30" Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=GridViewColumnHeader},Path=ActualWidth}" IsEnabled="False"/>
            </StackPanel>
        </DataTemplate>
    </Window.Resources>
    
    <Grid>
        <StackPanel>
            <Grid Background="AliceBlue">
                <Label Content="Basic Table"/>
                <Button Content="Load Data" Margin="5,5,5,5" Click="Button_Click" HorizontalAlignment="Right"/>
            </Grid>            
            <ListView x:Name="listView1" Height="100" ItemsSource="{Binding Path=DataTable}" Background="WhiteSmoke" SelectionChanged="listView1_SelectionChanged" ToolTip="Click to Remove Row" GridViewColumnHeader.Click="listView1_Click">
                <ListView.View>
                    <GridView x:Name="gridView1" ColumnHeaderTemplate="{StaticResource OverwriteHeaderTemplate}">
                        <GridView.Columns>
                            <GridViewColumn Header="Number" DisplayMemberBinding="{Binding Path=Number}" Width="100"/>
                            <GridViewColumn Header="Text" DisplayMemberBinding="{Binding Path=Text}" Width="100"/>
                        </GridView.Columns>
                    </GridView>
                </ListView.View>
            </ListView>
            <Grid Background="AliceBlue">
                <Label Content="Copy Table"/>
                <Button Content="Copy with Overwrites" Margin="5,5,5,5" Click="Button_Click_1" HorizontalAlignment="Right"/>
            </Grid>
            <ListView x:Name="listView2" Height="100" ItemsSource="{Binding Path=DataTable2}" Background="WhiteSmoke">
                <ListView.View>
                    <GridView x:Name="gridView2">
                        <GridView.Columns>
                            <GridViewColumn Header="Number" DisplayMemberBinding="{Binding Path=Number}" Width="100"/>
                            <GridViewColumn Header="Text" DisplayMemberBinding="{Binding Path=Text}" Width="100"/>
                        </GridView.Columns>
                    </GridView>
                </ListView.View>
            </ListView>
        </StackPanel>
    </Grid>
</Window>
public partial class Window2 : Window
    {
        private DataTable dataTable = new DataTable();
        private DataTable dataTable2 = new DataTable();
        Dictionary<string, Overwrite> _overwriteColumns = new Dictionary<string, Overwrite>();
        public Window2()
        {
            Init();
            InitializeComponent();            
        }
        private void Init()
        {
            dataTable = new DataTable();
            dataTable.Columns.Add("Number", typeof(int));
            dataTable.Columns.Add("Text", typeof(string));            
            dataTable2 = new DataTable();
            dataTable2.Columns.Add("Number", typeof(int));
            dataTable2.Columns.Add("Text", typeof(string));            
        }
        public DataTable DataTable
        {
            get
            {                
                return dataTable;
            }
        }
        public DataTable DataTable2
        {
            get
            {
                return dataTable2;
            }
        }
        private DataTable GetDataTable()
        {
            DataTable dataTable = new DataTable();
            dataTable.Columns.Add("Number", typeof(int));
            dataTable.Columns.Add("Text", typeof(string));            
            DataRow row = dataTable.NewRow();
            int nextRow = dataTable.Rows.Count + 1;
            row["Number"] = nextRow;
            row["Text"] = string.Format("Row {0}", nextRow);            
            dataTable.Rows.Add(row);
            row = dataTable.NewRow();
            nextRow = dataTable.Rows.Count + 1;
            row["Number"] = nextRow;
            row["Text"] = string.Format("Row {0}", nextRow);            
            dataTable.Rows.Add(row);
            return dataTable;
        }
        private void FillListView(DataTable dt)
        {
            dataTable = null;
            dataTable = new DataTable();
            _overwriteColumns.Clear();
            gridView1.Columns.Clear();
            dataTable.BeginLoadData();
            foreach (DataColumn column in dt.Columns)
            {
                dataTable.Columns.Add(column.ColumnName, column.DataType);
            }
            foreach (DataRow row in dt.Rows)
            {
                dataTable.ImportRow(row);
            }
            dataTable.EndLoadData();
            listView1.ItemsSource = dataTable.DefaultView;
            DataTemplate dataTemplate = (DataTemplate)this.FindResource("OverwriteHeaderTemplate");
            foreach (DataColumn column in dt.Columns)
            {
                _overwriteColumns.Add(column.ColumnName, new Overwrite(column.ColumnName, string.Empty));
                GridViewColumn c = new GridViewColumn();
                c.Header = _overwriteColumns[column.ColumnName];
                c.DisplayMemberBinding = new Binding(column.ColumnName);
                c.HeaderTemplate = dataTemplate;
                gridView1.Columns.Add(c);
            }
        }
        private string GetValue(DataRow row, DataColumn column)
        {
            string result = string.Empty;
            if (row.IsNull(column.ColumnName))
            {
                result = "NULL";
            }
            else if (column.DataType == typeof(string))
            {
                result = string.Format("'{0}'", ((string)row[column.ColumnName]).Trim());
            }
            else if (column.DataType == typeof(int))
            {
                result = ((int)row[column.ColumnName]).ToString();
            }
            else if (column.DataType == typeof(float))
            {
                result = ((float)row[column.ColumnName]).ToString();
            }
            else if (column.DataType == typeof(bool))
            {
                bool v = (bool)row[column.ColumnName];
                result = (v) ? "1" : "0";
            }
            else if (column.DataType == typeof(DateTime))
            {
                result = string.Format("'{0}'", ((DateTime)row[column.ColumnName]).ToString("yyyy/MM/dd HH:mm:ss.fff"));
            }
            return result;
        }
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            FillListView(GetDataTable());
        }
        private void listView1_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if(e.AddedItems.Count>0)
            {
                DataRowView rowView = (DataRowView)e.AddedItems[0];
                DataRow row = rowView.Row;                 
                dataTable.Rows.Remove(row);
            }
        }
        private childItem FindVisualChild<childItem>(DependencyObject obj)
            where childItem : DependencyObject
        {
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
            {
                DependencyObject child = VisualTreeHelper.GetChild(obj, i);
                if (child != null && child is childItem)
                    return (childItem)child;
                else
                {
                    childItem childOfChild = FindVisualChild<childItem>(child);
                    if (childOfChild != null)
                        return childOfChild;
                }
            }
            return null;
        }
        internal class Overwrite
        {
            public static int TYPE_NORMAL = 0;
            public static int TYPE_OVERWRITE = 1;
            public Overwrite(string columnName, string overwriteText)
            {
                this.ColumnName = columnName;
                this.OverwriteText = overwriteText;
                this.ColumnType = TYPE_NORMAL;
            }
            public string ColumnName { get; set; }
            public string OverwriteText { get; set; }
            public int ColumnType { get; set; }
        }
        private void listView1_Click(object sender, RoutedEventArgs e)
        {
            GridViewColumnHeader header = e.OriginalSource as GridViewColumnHeader;
            Overwrite overwrite = (Overwrite)header.Column.Header;
            ContentPresenter myContentPresenter = FindVisualChild<ContentPresenter>(header);
            DataTemplate dataTemplate = myContentPresenter.ContentTemplate;
            var overwriteTextBox = (TextBox)dataTemplate.FindName("overwriteText", myContentPresenter);
            if (header.Background == Brushes.LightSalmon)
            {
                overwrite.ColumnType = Overwrite.TYPE_NORMAL;
                header.Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FFD4D0C8"));
                overwriteTextBox.IsEnabled = false;
            }
            else
            {
                overwrite.OverwriteText = overwriteTextBox.Text;
                overwrite.ColumnType = Overwrite.TYPE_OVERWRITE;
                header.Background = Brushes.LightSalmon;
                overwriteTextBox.IsEnabled = true;
            } 
        }
        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            dataTable2.Clear();
            foreach (DataRow row in dataTable.Rows)
            {
                DataRow row2 = dataTable2.NewRow();
                foreach (DataColumn column in dataTable.Columns)
                {
                    if (_overwriteColumns[column.ColumnName].ColumnType == Overwrite.TYPE_OVERWRITE)
                    {
                        string overwriteText = _overwriteColumns[column.ColumnName].OverwriteText;
                        row2[column.ColumnName] = overwriteText;
                    }
                    else if (_overwriteColumns[column.ColumnName].ColumnType == Overwrite.TYPE_NORMAL)
                    {
                        row2[column.ColumnName] = row[column.ColumnName];
                    }
                }
                dataTable2.Rows.Add(row2);
            }
        }
    }

No comments:

Post a Comment