Question

I'm binding to an Xceed DataGridControl (Community Edition) with AutoCreatedColumns

ObservableCollection<ItemViewModel> Items

I would like to mark the created columns' ReadOnly property based on the Editable attribute on the viewmodel property.

 class ItemViewModel : ViewModelBase {

     [Editable(false)] 
     public string Id { get; set; }

     string _comment;
     [Editable(true)]
     public string Comment {
         get { return _comment; }
         set {
              _comment = value;
              NotifyOfPropertyChanged(() => Comment);
         }
     // Other properties ...

 }

Is this possible? or is there another way I could hook into the creation of the column to inspect the property that is being bound and programmatically set ReadOnly?

Was it helpful?

Solution

I think the optimal solution is to just hook up to ItemsSourceChangeCompleted event like this:

void _dataGrid_ItemsSourceChangeCompleted(object sender, EventArgs e)
{
    DataGridControl control = (DataGridControl)sender;
    Type itemType = control.ItemsSource.GetType().GenericTypeArguments[0];
    foreach (var col in control.Columns)
    {
        PropertyInfo propInfo = itemType.GetProperty(col.FieldName);
        if (propInfo != null)
        {
            EditableAttribute editableAttribute = propInfo.GetCustomAttributes().OfType<EditableAttribute>().FirstOrDefault();
            col.ReadOnly = (editableAttribute == null || !editableAttribute.Value);
        }
        else
        {
            col.ReadOnly = false;
        }
    }
}

Alternatively, you could bind the cell ReadOnly property to your editable attribute as described here.

If you know what columns you want to display you could simplify the solution above and bind the column ReadOnly property like this:

public class EditableConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value != null)
        {
            PropertyInfo propInfo = value.GetType().GenericTypeArguments[0].GetProperty(parameter.ToString());
            if (propInfo != null)
            {
                EditableAttribute editableAttribute = propInfo.GetCustomAttributes().OfType<EditableAttribute>().FirstOrDefault();
                return (editableAttribute == null || !editableAttribute.Value);
            }
        }
        return false;
    }
    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}
<xcdg:DataGridControl.Columns>
    <xcdg:Column FieldName="Id" 
                 ReadOnly="{Binding RelativeSource={RelativeSource Self}, 
                    Path=DataGridControl.ItemsSource, 
                    Converter={StaticResource EditableConverter}, ConverterParameter=Id}" />
    <xcdg:Column FieldName="Comment" 
                 ReadOnly="{Binding RelativeSource={RelativeSource Self}, 
                    Path=DataGridControl.ItemsSource, 
                    Converter={StaticResource EditableConverter}, ConverterParameter=Comment}" />
</xcdg:DataGridControl.Columns>

But then, you might as well turn off AutoCreateColumns and define the Columns collection by yourself in code (or turn off AutoCreateItemProperties and create your own DataGridCollectionViewSource where you set each DataGridItemProperty.IsReadOnly appropriately).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top