Search code examples
wpfdatagriddatagridtemplatecolumn

WPF DataGrid : TemplateColumn with UserControl and TextBlock


Im a bit stuck here.. been searching for two days and found no solution.

What i would like to achieve is the behavior of DataGridComboBoxColumn . I need its DisplayMemberPath, SelectedValuePath and SelectedValueBinding properties..

Im having my UserControl similar to ComboBox in the CellEditingTemplate and TextBlock in CellTemplate.

Im doing all these in code, since these columns may not exist necessarily..

This is where i define the TemplateColumn :

DataGridTemplateColumn tcol = new DataGridTemplateColumn();
tcol.Header = "accCust";

FrameworkElementFactory texttablF = new FrameworkElementFactory(typeof(TextTableBox));
texttablF.SetValue(TextTableBox.TableSourceProperty, accTable.DefaultView);

FrameworkElementFactory tb = new FrameworkElementFactory(typeof(TextBlock));
texttablF.SetBinding(TextBlock.TextProperty, new Binding("Account"));


tcol.CellTemplate = new DataTemplate(typeof(DataGridCell)) { VisualTree = tb };
tcol.CellEditingTemplate = new DataTemplate(typeof(DataGridCell)) { VisualTree = texttablF };

I have two issues :

  1. TextBlock shows the ID present in the DataGrid's Table, I want it to show the value specified in the DisplayMemberPath, which i have no idea how to implement.
  2. The DependencyProperty TableSource isnt working when done via FrameworkElement.setValue.. It works when it is done in the normal way, ie

    TextTableBox ttb = new TextTableBox();
    ttb.TableSource = src_table.DefaultView;
    

I hope its clear to you what my problem is.. All i really want is to replace the ComboBox in DataGridComboColumn with my UserControl..

Thanks in advance :) Im sorry if it is a poor question.. Im new to WPF and doing my HighSchools..


Solution

  • Because i wanted the Properties of ComboBox, i had to inherit from DataGridComboBoxColumn.

    Heres how the code looks like :

    public class DataGridTCBColumn : DataGridComboBoxColumn
    {
        private TableComboBox comboBox;
    
        public DataGridTCBColumn(bool Editable)
        {
            comboBox = new TableComboBox() { IsEditable = Editable };
        }
    
        // Requires extra field..
        public string SelectedValuePathX
        {
            get
            {
                return (string)this.GetValue(SelectedValuePathXProperty);
            }
            set
            {
    
                this.SetValue(SelectedValuePathXProperty, value);
    
            }
        }
        static FrameworkPropertyMetadata SelectedValuePathXPropertyMeta = new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, new PropertyChangedCallback(SelectedValuePathXPropertyChanged));
        public static readonly DependencyProperty SelectedValuePathXProperty =
    DependencyProperty.Register("SelectedValueX", typeof(string), typeof(TableComboBox), SelectedValuePathXPropertyMeta);
        private static void SelectedValuePathXPropertyChanged(DependencyObject dobj, DependencyPropertyChangedEventArgs e)
        {}
    
        protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
        {
            if (e.Property == DataGridTCBColumn.ItemsSourceProperty)
            {
                comboBox.ItemsSource = ItemsSource;
            }
            else if (e.Property == DataGridTCBColumn.SelectedValuePathProperty)
            {
                comboBox.SelectedValuePath = SelectedValuePath;
            }
            else if (e.Property == DataGridTCBColumn.DisplayMemberPathProperty)
            {
                comboBox.DisplayMemberPath = DisplayMemberPath;
            }
    
            base.OnPropertyChanged(e);
        }
    
    
        protected override FrameworkElement GenerateEditingElement(DataGridCell cell, object dataItem)
        {
            return comboBox;
        }
        protected override object PrepareCellForEdit(FrameworkElement editingElement, RoutedEventArgs editingEventArgs)
        {
            DataGridCell cell = editingEventArgs.Source as DataGridCell;
            if (cell != null && !string.IsNullOrEmpty(this.SelectedValuePathX))
            {
                //For Typed DataSet
                object obj = ((DataRowView)editingElement.DataContext).Row[this.SelectedValuePathX];
                comboBox.SelectedValue = obj;
            }
    
            comboBox.Focus();
            return comboBox.SelectedItem;
        }
        protected override bool CommitCellEdit(FrameworkElement editingElement)
        {   
            if (!string.IsNullOrEmpty(this.SelectedValuePathX) && comboBox.SelectedValue != null)
            ((DataRowView)editingElement.DataContext).Row[this.SelectedValuePathX] = comboBox.SelectedValue;
            return true;
        }
    }
    

    Had to make another dependency propertry SelectedValuePathX. Actually, it does the job of SelectedValueBinding. However that Binding never did work (tried goin through the source code of ComboBox (Microsoft Reference Source) but dint work out well either.

    Hopes it would help somebody :)