How to add a DataGridTemplateColumn using a button to a WPFToolkit DataGrid that is bound to a DataTable?

Ok, so here is my goal. I have a DataGrid that is going to be bound to a DataTable.

I want to add a DataGridTemplateColumn when the DataContext changes.

For each row, I have an value that is either normal, warning, or error. If normal, I don’t want a button on the column at all. If error or warning, I want a button.

So the DataTable looks something like this but in my larger app (this is a minimal example) the data is dynamic in that it can contain different numbers of rows, difference column names, etc. So a static View and static binding isn’t going to work.

FieldValueCompare
a11
b23
c35
d44

So, the idea is to get the WPFToolkit’s DataGrid view to look like this.  If the numbers differ by 1, it is a warning.  If the numbers differ by 2 it is an error.

FieldValueCompareAction
a11Normal
b23
c35
d44Normal

So how do I do this with a WPFToolKit DataGrid that is bound to a Table?

Hopefully, I will figure this out:
Windows 7 64 bit
Visual Studio 2008 SP1
.NET 3.5
WPToolKit

I don’t have it working yet…

Step 1 – Create a new WPF Application project in Visual Studio

Step 2 – Add WPFToolKit as a Reference

  1. Right-click on project and choose Add Reference.
  2. Under the first tab called .NET select WPFToolkit.

Step 3 – Create the View

  1. Open the Window1.xaml.
    <Window x:Class="DataGridAddButtonColumnTest.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:wpftk="clr-namespace:Microsoft.Windows.Controls;assembly=WPFToolkit"
        Title="Window1" Height="300" Width="300" Loaded="Window_Loaded">
        <Grid>
            <wpftk:DataGrid ItemsSource="{Binding}" Name="mDataGrid" CanUserAddRows="False" IsReadOnly="True" DataContextChanged="mDataGrid_DataContextChanged"></wpftk:DataGrid>
        </Grid>
    </Window>
    
    

Step 4 – Create the Data

  1. Create a TestData class.
    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Linq;
    using System.Text;
    
    namespace DataGridAddButtonColumnTest
    {
        public class TestData
        {
            #region Member Variables
            DataTable mTable;
            #endregion
    
            #region Constructors
    
    		 /*
    		 * The default constructor
     		 */
            public TestData()
            {
                mTable = MakeSampleDataTable();
            }
    
            #endregion
    
            #region Properties
    
            public DataTable Table
            {
                get { return mTable; }
                set { mTable = value; }
            }
    
    
            #endregion
    
            #region Functions
            private DataTable MakeSampleDataTable()
            {
                DataTable table = new DataTable();
                table.Columns.Add("Field", typeof(string));
                table.Columns.Add("Value", typeof(int));
                table.Columns.Add("Compare", typeof(string));
                //table.Columns.Add("Action", typeof(string));
    
                table.Rows.Add("a", "1", "1");
                table.Rows.Add("b", "2", "3");
                table.Rows.Add("c", "3", "5");
                table.Rows.Add("d", "4", "1");
    
                // Or should I include the button data here or not?
                //DataTable table = new DataTable();
                //table.Columns.Add("Field", typeof(string));
                //table.Columns.Add("Value", typeof(int));
                //table.Columns.Add("Compare", typeof(string));
                //table.Columns.Add("Action", typeof(string));
    
                //table.Rows.Add("a", "1", "1", "Normal");
                //table.Rows.Add("b", "2", "3", "Warning");
                //table.Rows.Add("c", "3", "5", "Error");
                //table.Rows.Add("d", "4", "1", "Normal");
    
    
                return table;
            }
            #endregion
        }
    }
    [/source]
    </li>
    	<li>Create a TestDataModel Class
    
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Linq;
    using System.Text;
    
    namespace DataGridAddButtonColumnTest
    {
        public class TestDataModel : INotifyPropertyChanged
        {
            #region Member Variables
            readonly TestData mTestData;
            public event PropertyChangedEventHandler PropertyChanged;
    
            #endregion
    
            #region Constructors
    
            /*
    		 * The default constructor
     		 */
            public TestDataModel(TestData inTestData)
            {
                mTestData = inTestData;
            }
    
            #endregion
    
            #region Properties
            public DataView View
            {
                get { return mTestData.Table.DefaultView; }
            }
    
            public TestData TestData
            {
                get { return mTestData; }
            }
    
            #endregion
    
            #region Functions
            #endregion
    
            #region Enums
            #endregion
    
            // Not sure if I even need to implement this for this test
            #region INotifyPropertyChanged Members
            protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
            {
    
                if (this.PropertyChanged != null)
    
                    this.PropertyChanged(this, e);
            }
    
            #endregion
        }
    }
    
  2. Add code to the Window1.xaml.cs file
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Controls.Primitives;
    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 Microsoft.Windows.Controls;
    
    namespace DataGridAddButtonColumnTest
    {
        /// <summary>
        /// Interaction logic for Window1.xaml
        /// </summary>
        public partial class Window1 : Window
        {
            public Window1()
            {
                InitializeComponent();
            }
    
            private void Window_Loaded(object sender, RoutedEventArgs e)
            {
                TestData td = new TestData();
                TestDataModel tdm = new TestDataModel(td);
                mDataGrid.DataContext = tdm.View;
                CreateActionButtonColumn();
            }
    
            private void mDataGrid_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
            {
    
            }
    
            public void CreateActionButtonColumn()
            {
                Binding binding = new Binding("PropertyName") { Mode = BindingMode.TwoWay };
                DataGridTemplateColumn templateColumn = new DataGridTemplateColumn { CanUserReorder = false, Width = 85, CanUserSort = true };
                BindingOperations.SetBinding(templateColumn, DataGridColumn.HeaderProperty, binding);
                DataTemplate dataTemplate = new DataTemplate();
                FrameworkElementFactory tmpButton = new FrameworkElementFactory(typeof(Button));
                tmpButton.SetBinding(Button.NameProperty, binding);
                dataTemplate.VisualTree = tmpButton;
                templateColumn.CellTemplate = dataTemplate;
                mDataGrid.Columns.Add(templateColumn);
    
            }
    
        }
    }
    
    

Help! I don’t know how to finish this…

UPDATE 3/22/2010
I have an answer from http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/6619249d-4353-4747-b3ad-d2748ac26d7b.

I will re-write this post with the correct details.

Leave a Reply

How to post code in comments?

*