The answer linked by viky summarizes the idea of adding the button column from source. I ve put together a short example that also shows the second part of your question, which is how to enable/disable the button based on the data in the grid. I used the DataGrid in 4.0, but the toolkit with 3.5 should be fine as well.
First, I add one Name column from XAML. This isn t necessary, but just shows that you can do a combination of XAML and C# additions to the grid. Note that I name the grid here so that I have a way to refer to it in the C# partial class.
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Data Grid Populated in XAML and C#">
<Grid>
<DataGrid x:Name="_gridControl" IsReadOnly="True" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Width="*" Binding="{Binding Name}"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
Now, I do two things in the code behind. Aside from adding the button column and the data elements (which have a Name and a Status), I create a Converter class that will return true if the value is "Open" and false otherwise. Then, when setting the Binding (as opposed to value), I also add my converter so that when the ItemsControl generates and binds containers for my items, the Button displayed has its IsEnabled state linked to the Status field of my item.
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var buttonTemplate = new FrameworkElementFactory(typeof(Button));
buttonTemplate.SetBinding(Button.ContentProperty, new Binding("Name"));
buttonTemplate.SetBinding(Button.IsEnabledProperty, new Binding("Status")
{
Converter = new StatusToEnabledConverter()
});
buttonTemplate.AddHandler(
Button.ClickEvent,
new RoutedEventHandler((o, e) => MessageBox.Show("hi"))
);
this._gridControl.Columns.Add(
new DataGridTemplateColumn()
{
Header = "Close Button",
CellTemplate = new DataTemplate() { VisualTree = buttonTemplate }
}
);
this._gridControl.ItemsSource = new object[]
{
new { Name = "First Item", Status = "Open" },
new { Name = "Second Item", Status = "Open" },
new { Name = "Third Item", Status = "Closed" },
new { Name = "Fourth Item", Status = "Closed" },
new { Name = "Fifth Item", Status = "Open" }
};
}
}
public class StatusToEnabledConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter,
CultureInfo culture)
{
return "Open".Equals(value);
}
public object ConvertBack(object value, Type targetType, object parameter,
CultureInfo culture)
{
throw new System.NotImplementedException();
}
}
One final important note is that I only modify the DataGrid from C# after InitializeComponent is called. For a WPF content control that has a XAML and C# part, this is important, as the object construction done via XAML needs to have completed before you start modifying the objects defined in XAML.
Hope this helps!