views:

667

answers:

2

It seems like no matter what i do, i get AG_E_PARSER_PROPERTY_NOT_FOUND when trying to bind a property in DataGridTemplateColumn in silverlight. I've even tried tried the following

            <data:DataGridTemplateColumn dataBehaviors:DataGridColumnBehaviors.BindableTextOverride="{Binding ElementName=LayoutRoot, 
                                                                                                              Path=DataContext.ColumnOneName}">
                <data:DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding Name}" />
                    </DataTemplate>
                </data:DataGridTemplateColumn.CellTemplate>
                <data:DataGridTemplateColumn.CellEditingTemplate>
                    <DataTemplate>
                        <TextBox Text="{Binding Name, Mode=TwoWay}" />
                    </DataTemplate>
                </data:DataGridTemplateColumn.CellEditingTemplate>
            </data:DataGridTemplateColumn>

But no luck... I know the DataGridTemplateColumn does not contain a DataContext, but i don't feel like this should be the cause of the problem when I'm giving it the element and path to bind to. Any ideas?

A: 

Does the ColumnOneName property have a Name property ?

Timores
A: 

Turns out the only way to get this to work is to implement it like DataGridBoundColumn. The idea is to bind to the binding property. This property will internally set the binding to a private DependencyProperty. When that property changes, you can perform anything needed inside the DependencyProperty Change Callback.

Here is an example:

/// <summary>   
/// Represents a System.Windows.Controls.DataGrid column that can bind to a property
/// in the grid's data source.  This class provides bindable properties ending with the suffix Binding. 
/// These properties will affect the properties with the same name without the suffix
/// </summary>
public class DataGridBindableTemplateColumn : DataGridBoundColumn
{
    /// <summary>
    /// Identifies the DataGridBindableTemplateColumn.HeaderValueProperty dependency property
    /// </summary>
    internal static readonly DependencyProperty HeaderValueProperty =
        DependencyProperty.Register("HeaderValue", typeof(object), typeof(DataGridBindableTemplateColumn),
            new PropertyMetadata(null, OnHeaderValuePropertyChanged));

    /// <summary>
    /// Identifies the DataGridBindableTemplateColumn.VisibilityValueProperty dependency property
    /// </summary>
    internal static readonly DependencyProperty VisibilityValueProperty =
        DependencyProperty.Register("VisibilityValue", typeof(Visibility), typeof(DataGridBindableTemplateColumn),
            new PropertyMetadata(Visibility.Visible, OnVisibilityPropertyPropertyChanged));

    /// <summary>
    /// The callback the fires when the VisibilityValueProperty value changes
    /// </summary>
    /// <param name="d">The DependencyObject from which the property changed</param>
    /// <param name="e">The DependencyPropertyChangedEventArgs containing the old and new value for the depenendency property that changed.</param>
    private static void OnVisibilityPropertyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        DataGridBindableTemplateColumn sender = d as DataGridBindableTemplateColumn;

        if (sender != null)
        {
            sender.OnVisibilityPropertyChanged((Visibility)e.OldValue, (Visibility)e.NewValue);
        }
    }

    /// <summary>
    /// The callback the fires when the HeaderValueProperty value changes
    /// </summary>
    /// <param name="d">The DependencyObject from which the property changed</param>
    /// <param name="e">The DependencyPropertyChangedEventArgs containing the old and new value for the depenendency property that changed.</param>
    private static void OnHeaderValuePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        DataGridBindableTemplateColumn sender = d as DataGridBindableTemplateColumn;

        if (sender != null)
        {
            sender.OnHeaderValueChanged((object)e.OldValue, (object)e.NewValue);
        }
    }

    private Binding _headerBinding;
    private Binding _visibilityBinding;

    private DataTemplate _cellEditingTemplate;
    private DataTemplate _cellTemplate;

    /// <summary>
    /// Gets and sets the Binding object used to bind to the Header property
    /// </summary>
    public Binding HeaderBinding
    {
        get { return _headerBinding; }
        set 
        {
            if (_headerBinding != value)
            {                    
                _headerBinding = value;

                if (_headerBinding != null)
                {                        
                    _headerBinding.ValidatesOnExceptions = false;
                    _headerBinding.NotifyOnValidationError = false;

                    BindingOperations.SetBinding(this, HeaderValueProperty, _headerBinding);
                }
            }
        }
    }

    /// <summary>
    /// Gets and sets the Binding object used to bind to the Visibility property
    /// </summary>
    public Binding VisibilityBinding
    {
        get { return _visibilityBinding; }
        set
        {
            if (_visibilityBinding != value)
            {
                _visibilityBinding = value;

                if (_visibilityBinding != null)
                {
                    _visibilityBinding.ValidatesOnExceptions = false;
                    _visibilityBinding.NotifyOnValidationError = false;

                    BindingOperations.SetBinding(this, VisibilityValueProperty, _visibilityBinding);
                }
            }
        }
    }

    /// <summary>
    /// Gets or sets the template that is used to display the contents of a cell
    /// that is in editing mode.
    /// </summary>
    public DataTemplate CellEditingTemplate
    {
        get { return _cellEditingTemplate; }
        set
        {
            if (_cellEditingTemplate != value)
            {
                _cellEditingTemplate = value;
            }
        }
    }

    /// <summary>
    /// Gets or sets the template that is used to display the contents of a cell
    /// that is not in editing mode.
    /// </summary>
    public DataTemplate CellTemplate
    {
        get { return _cellTemplate; }
        set
        {
            if (_cellTemplate != value)
            {
                _cellTemplate = value;
            }
        }
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="editingElement"></param>
    /// <param name="uneditedValue"></param>
    protected override void CancelCellEdit(FrameworkElement editingElement, object uneditedValue)
    {
        editingElement = GenerateEditingElement(null, null);
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="cell"></param>
    /// <param name="dataItem"></param>
    /// <returns></returns>
    protected override FrameworkElement GenerateEditingElement(DataGridCell cell, object dataItem)
    {
        if (CellEditingTemplate != null)
        {
            return (CellEditingTemplate.LoadContent() as FrameworkElement);
        }

        if (CellTemplate != null)
        {
            return (CellTemplate.LoadContent() as FrameworkElement);
        }

        if (!DesignerProperties.IsInDesignTool)
        {
            throw new Exception(string.Format("Missing template for type '{0}'", typeof(DataGridBindableTemplateColumn)));
        }

        return null;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="cell"></param>
    /// <param name="dataItem"></param>
    /// <returns></returns>
    protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem)
    {
        if (CellTemplate != null)
        {
            return (CellTemplate.LoadContent() as FrameworkElement);
        }

        if (CellEditingTemplate != null)
        {
            return (CellEditingTemplate.LoadContent() as FrameworkElement);
        }

        if (!DesignerProperties.IsInDesignTool)
        {
            throw new Exception(string.Format("Missing template for type '{0}'", typeof(DataGridBindableTemplateColumn)));
        }

        return null;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="editingElement"></param>
    /// <param name="editingEventArgs"></param>
    /// <returns></returns>
    protected override object PrepareCellForEdit(FrameworkElement editingElement, RoutedEventArgs editingEventArgs)
    {
        return null;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="oldValue"></param>
    /// <param name="newValue"></param>
    protected virtual void OnHeaderValueChanged(object oldValue, object newValue)
    {
        Header = newValue;
    }

    /// <summary>
    /// I'm to lazy to write a comment
    /// </summary>
    /// <param name="oldValue"></param>
    /// <param name="newValue"></param>
    protected virtual void OnVisibilityPropertyChanged(Visibility oldValue, Visibility newValue)
    {
        Visibility = newValue;
    }
}

XAML:

    <data:DataGridBindableTemplateColumn HeaderBinding="{Binding HeaderOne, Source={StaticResource ViewModel}}"
                                         VisibilityBinding="{Binding HeaderOneVisibility, Source={StaticResource ViewMode}}"
                                         HeaderStyle="{StaticResource DataColumnStyle}"
                                         MinWidth="58">
                        ...
    </data:DataGridBindableTemplateColumn>

Hope this helps anyone with the same issue... Enjoy!

Jeff
I tried the above code, but I am getting "target is not of type FrameworkElement or CollectionViewSource." exception... on the visibilitybinding when BindingOperations.SetBinding(this,..) is called, any ideas?
Titan