I'm working on a WPF application that makes heavy use of data grids. I have a situation that comes up frequently that requires me to use a custom control within a data grid. Of course, the data being bound is different for each row.
My approach to the problem, was to make a custom control that was of the type DataGridTemplateColumn and add my own dependency properties to it. Then when I need to use this column type in my grids, I can do it in one line.
It seems like the data context of the custom control is all out of whack.
Right now, I have the following code...
DataGridCheckedComboColumn.xaml
<DataGridTemplateColumn x:Class="DataTracker.Presentation.GridControls.Views.DataGridCheckedComboColumn"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:ccb="clr-namespace:CheckedComboBoxControl;assembly=CheckedComboBox"
mc:Ignorable="d">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ccb:CheckedComboBox ItemsSource="{Binding Path=ComboSource}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ccb:CheckedComboBox ItemsSource="{Binding Path=ComboSource}" />
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
And this for code behind...
DataGridCheckedComboColumn.xaml.cs
namespace DataTracker.Presentation.GridControls.Views
{
/// <summary>
/// Interaction logic for DataGridCheckedComboColumn.xaml
/// </summary>
public partial class DataGridCheckedComboColumn : DataGridTemplateColumn
{
public DataGridCheckedComboColumn()
{
InitializeComponent();
}
/// <summary>
/// Gets or sets the runway data.
/// </summary>
/// <value>The runway data.</value>
public IEnumerable<Object> ComboSource
{
get
{
return (IEnumerable<Object>)this.GetValue(ComboSourceProperty);
}
set
{
this.SetValue(ComboSourceProperty, value);
}
}
private static void OnComboSourceChanged(DependencyObject dependentView, DependencyPropertyChangedEventArgs e)
{
/////////////////////////////////////////////////////////////////
// //
// This is the code I used when I was making user controls and //
// sending data to the view models //
// //
// //
// Not sure what, if anything to do here now... //
// //
/////////////////////////////////////////////////////////////////
//var control = (DataGridComboColumn)dependentView;
//var viewModel = (DataGridComboColumnViewModel)control.DataContext;
//viewModel.ComboSource = (IEnumerable<Object>)e.NewValue;
}
public static readonly DependencyProperty ComboSourceProperty =
DependencyProperty.Register("ComboSource",
typeof(IEnumerable<Object>),
typeof(DataGridCheckedComboColumn),
new FrameworkPropertyMetadata()
{
PropertyChangedCallback = OnComboSourceChanged,
BindsTwoWayByDefault = true
});
}
}
I add the custom control to my data grid like so...
<gc:DataGridCheckedComboColumn ComboSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl, AncestorLevel=1}, Path=DataContext.DataVersions}" />
Everything renders appropriately, but no matter what data I pass through, nothing makes it. I've even hard coded lists and sent those, but no luck. I've also tried sending other simple properties like strings, but that has failed too.
WPF gives the following error. I should point out that "GenericGridObject" is what I am populating the full data grid with.
System.Windows.Data Error: 40 : BindingExpression path error: 'ComboSource' property not found on 'object' ''GenericGridObject`1' (HashCode=37030675)'. BindingExpression:Path=ComboSource; DataItem='GenericGridObject`1' (HashCode=37030675); target element is 'CheckedComboBox' (Name=''); target property is 'ItemsSource' (type 'IEnumerable')
Like I said before, I think this is an issue with the data context of the custom control, but I can't seem to figure out how to force it to use its own class as the data context rather than the data context of the overall grid.
Any ideas?