Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DataGridTextColumn - How to bind IsReadonly?

In Silverlight 4, the IsReadOnly property of DataGridTextColumn seems to be no dependency property. Hence I could not bind it to a property on the viewmodel.

It seems the only alternative is using a DataTemplate, but even here I am facing two major problems:

<sdk:DataGrid Style="{StaticResource DataGridStyle}" x:Name="call_dataGrid" ItemsSource="{Binding Calls}">
                    <sdk:DataGrid.Columns>
                        <sdk:DataGridTextColumn Header="Call Time" Binding="{Binding Path=CallTime}" />
                        <sdk:DataGridTemplateColumn Header="Call Date">
                            <sdk:DataGridTemplateColumn.CellEditingTemplate>
                                <DataTemplate>
                                    <TextBox Text="{Binding Path=CallDate}" IsReadOnly="{Binding Path=DataContext.IsInEditMode, ElementName=call_dataGrid, Converter={StaticResource NegationConverter}}"/>
                                </DataTemplate>
                            </sdk:DataGridTemplateColumn.CellEditingTemplate>
                        </sdk:DataGridTemplateColumn>

It seems I can't edit a template of DataGridTextColumn and have to use DataGridTemplateColumn instead as seen above. This however overrides all the styles I had previously defined within the DataGridStyle. My Column doesn't even have the row marker and looks totally alien to the rest of the cells.

Second problem is, it still doesn't work as intended. The Textbox inside that template is still not set to readonly. What I am doing wrong here?

Highly appreciate your help on this,

Update

After the promising response below I have adjusted the code yet no success.

I have changed the DP's callback to the following

public class IsReadOnlyDpAttachable
    {
        public static void SetIsReadXOnly(DependencyObject obj, bool isReadOnly)
        {
            obj.SetValue(IsReadXOnlyProperty, isReadOnly);
        }

        public static bool GetIsReadXOnly(DependencyObject obj)
        {
            return (bool)obj.GetValue(IsReadXOnlyProperty);
        }

        public static readonly DependencyProperty IsReadXOnlyProperty =
            DependencyProperty.RegisterAttached("IsReadXOnly", typeof(bool), typeof(IsReadOnlyDpAttachable), new PropertyMetadata(false, Callback));

        private static void Callback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((DataGrid)d).IsReadOnly = (bool)e.NewValue;
        }
    }

And set the DP on the DataGrid's IsReadOnly itself, it works perfectly fine, but then again here I wouldn't need it since the IsReadOnly here is already a Dp and can be easily bound anyway. But the test shows the Dp works fine:

<sdk:DataGrid PrismExt:IsReadOnlyDpAttachable.IsReadXOnly="{Binding IsInEditMode, Mode=TwoWay, Converter={StaticResource NegationConverter}}" Style="{StaticResource DataGridStyle}" CanUserReorderColumns="True" x:Name="call_dataGrid" AutoGenerateColumns="False" ItemsSource="{Binding Calls}">

However the moment I try to utilize the DP on the underlying DataGridTextColumn, it doesn't do anything:

<Grid x:Name="LayoutRoot">
<sdk:DataGrid Style="{StaticResource DataGridStyle}" CanUserReorderColumns="True" x:Name="call_dataGrid" AutoGenerateColumns="False" ItemsSource="{Binding Calls}">
                    <sdk:DataGrid.Columns>                        
                        <sdk:DataGridTextColumn Header="Call Time" Binding="{Binding Path=CallTime}" PrismExt:IsReadOnlyDpAttachable.IsReadXOnly="{Binding DataContext.IsInEditMode, ElementName=LayoutRoot, Mode=TwoWay, Converter={StaticResource NegationConverter}}"/>
                    </sdk:DataGrid.Columns>
</sdk:DataGrid>
</Grid>

Any idea?

like image 308
Houman Avatar asked May 08 '11 10:05

Houman


1 Answers

what you can do is to create an attached property to handle the change of the IsReadOnly property in the DataGridTextColumn.

public class Class1
{
    public static void SetIsReadOnly(DependencyObject obj, bool isReadOnly)
    {
        obj.SetValue(IsReadOnlyProperty, isReadOnly);
    }

    public static bool GetIsReadOnly(DependencyObject obj)
    {
        return (bool)obj.GetValue(IsReadOnlyProperty);
    }

    // Using a DependencyProperty as the backing store for MyProperty.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty IsReadOnlyProperty =
        DependencyProperty.RegisterAttached("IsReadOnly", typeof(bool), typeof(Class1), new PropertyMetadata(false, Callback));

    private static void Callback(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        ((DataGridTextColumn)d).IsReadOnly = (bool)e.NewValue;
    }
}

In your xaml, you can just use the attached property instead.

<sdk:DataGridTextColumn local:Class1.IsReadOnly="True" Binding="{Binding Property1}" Header="Property1"/>

Hope this helps. :)

Update

Once you have the DataContextProxy class, you do

        <sdk:DataGridTextColumn Binding="{Binding Name}"
                                local:Class1.IsReadOnly="{Binding DataSource.IsInEditMode, Source={StaticResource DataContextProxy}, Converter={StaticResource xxxConverter}}"
                                Header="ReadOnly Header" />
like image 197
Justin XL Avatar answered Oct 09 '22 12:10

Justin XL