views:

658

answers:

2

Hello Silverlight gurus,

I am experiencing a problem with the DataGrid where my data-bound object's properties are not being updated when using the CellTemplate/CellEditingTemplate:

<data:DataGridTemplateColumn Header="Text">
    <data:DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Text}" ></TextBlock>
        </DataTemplate>
    </data:DataGridTemplateColumn.CellTemplate>
    <data:DataGridTemplateColumn.CellEditingTemplate>
        <DataTemplate>
            <TextBox Text="{Binding Text, Mode=TwoWay}" />
        </DataTemplate>
    </data:DataGridTemplateColumn.CellEditingTemplate>
</data:DataGridTemplateColumn>

I am binding to a code-gen'd entity via the RIA Services. I've added an event handler to the PropertyChanged event, and it is never fired. However, if I do not use a template and instead use a DataGridTextColumn, everything works fine.

I'm sure this sounds like an easy fix - I'm only using a TextBox in my editing template, so why not us a DataGridTextColumn? The problem is that I want to have a multi-line textbox, so using the DataGridTextColumn is not an option.

Any suggestions? Do you know of any differences between using a CellEditingTemplate containing a single TextBox and using a DataGridTextColumn?

Thanks,
-Charles

[UPDATE]
I posted a bug report here:
http://silverlight.net/forums/p/118729/267521.aspx

I can't imagine that this is "as-designed"... If someone else has known about this and I'm just being dumb, I'd appreciate an explanation - I'd prefer embarrassment over ignorance :).

A: 

I found a solution, but I can't explain why it makes a difference:

Change this...

<data:DataGridTemplateColumn Header="Text">
    <data:DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Text}" ></TextBlock>
        </DataTemplate>
    </data:DataGridTemplateColumn.CellTemplate>
    <data:DataGridTemplateColumn.CellEditingTemplate>
        <DataTemplate>
            <TextBox Text="{Binding Text, Mode=TwoWay}" />
        </DataTemplate>
    </data:DataGridTemplateColumn.CellEditingTemplate>
</data:DataGridTemplateColumn>

... to this:

<data:DataGridTemplateColumn Header="Text">
    <data:DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Text, Mode=OneWay}" ></TextBlock>
        </DataTemplate>
    </data:DataGridTemplateColumn.CellTemplate>
    <data:DataGridTemplateColumn.CellEditingTemplate>
        <DataTemplate>
            <TextBox Text="{Binding Text, Mode=TwoWay}" />
        </DataTemplate>
    </data:DataGridTemplateColumn.CellEditingTemplate>
</data:DataGridTemplateColumn>


Notice how I specified "Mode=OneWay" on the TextBlock's binding:

<TextBlock Text="{Binding Text, Mode=OneWay}" ></TextBlock>


I have no idea why this should make a difference. Even if the TextBlock was set to TwoWay, why wouldn't there be any changes made to the data-bound object?

An explanation would be greatly appreciated... I've spent about five hours banging my head against my keyboard just to get to this point, and I'd like to know why it is that I've made this mistake (assuming it's not a bug in Silverlight).

Thanks,
-Charles

Charles
Judging by the behaviour you're seeing, I'd say XML nodes are processed in-order and the ctor signature is determined once and cached.
Peter Wone
A: 

i "suspect" the problem lies with the default constructors for the Text property of the textbox.

Now the Text property is a dependecyproperty, when you call

 <TextBlock Text="{Binding Text}" ></TextBlock>

you actually call the constructor for the Text property that takes a single string value, in turn SL/WPF uses reflection to figure out which constructor is it, you can avoid this by using it in a named parameters style.

 <TextBlock Text="{Binding Path=Text}" ></TextBlock>

i think by not specify the mode it actually defaults to a one time binding, this is why OnPropertyChanged doesnt affect the value, since the binding only happens once. which kinda looks like below. Now the default for a textbox binding is "OneWay", maybe since its nested in a datagrid, its default behaviour is different. Maybe its doing the property inheritance thing and using the binding mode of the UI Control underneathe it.

<TextBlock Text="{Binding Text, Mode=OneTime}" ></TextBlock>

hence why when you specify the binding mode like so

<TextBlock Text="{Binding Text, Mode=OneWay}" ></TextBlock>

it works happily and readily

Neil