0
votes

I'm unable to get TwoWay Binding to work properly using DataGrid.Resources. The TextBox appears with the row on edit. When I exit off the row, the object that is bound to that row is not updated with the new value (tested with break points on the object that implements INotifyPropertyChanged).

Data binding was working properly prior to building out multiple Datatemplates outside of DataGrid.Resources.

<DataGrid AutoGenerateColumns="False" Name="dataGridProviderProperties" Height="215" FontSize="11" HorizontalGridLinesBrush="#FFC1C1C1" 
                          VerticalGridLinesBrush="#FFC1C1C1" Padding="0" Background="#00000000" EnableRowVirtualization="False"
                          HorizontalScrollBarVisibility="Auto" EnableColumnVirtualization="True" CanUserResizeRows="False" AlternationCount="2" 
                          AlternatingRowBackground="#05000000" CanUserAddRows="False" DataContext="{Binding}" ItemsSource="{Binding Properties}" VerticalAlignment="Center" Width="345" 
                          VerticalContentAlignment="Center">
                    <DataGrid.Resources>
                        <DataTemplate x:Key="IsSelectedColumnTemplate">
                            <TextBlock Text="{Binding Value}"/>
                        </DataTemplate>
                        <DataTemplate x:Key="IsSelectedColumnTemplateEditing">
                            <ContentControl x:Name="ControlHolder" Content="{Binding Value}">
                                <ContentControl.Resources>
                                    <DataTemplate DataType="{x:Type System:String}">
                                        <TextBox Text="{Binding ., Mode=TwoWay}" />
                                    </DataTemplate>
                                    <DataTemplate DataType="{x:Type System:Boolean}">
                                        <CheckBox IsChecked="{Binding}"/>
                                    </DataTemplate>
                                </ContentControl.Resources>
                            </ContentControl>
                        </DataTemplate>
                    </DataGrid.Resources>
                    <DataGrid.Columns>
                        <DataGridTemplateColumn Header="Key" Width="100">
                            <DataGridTemplateColumn.CellTemplate>
                                <DataTemplate>
                                    <Label VerticalContentAlignment="Center"  Height="27" VerticalAlignment="Center" Content="{Binding Key, Mode=OneWay}" Padding="3"></Label>
                                </DataTemplate>
                            </DataGridTemplateColumn.CellTemplate>
                        </DataGridTemplateColumn>
                        <DataGridTemplateColumn Header="Value" x:Name="myIsSelectedColumn" CellTemplate="{StaticResource IsSelectedColumnTemplate}"
                            CellEditingTemplate="{StaticResource IsSelectedColumnTemplateEditing}" CanUserSort="True" Width="Auto" />
                    </DataGrid.Columns>
                </DataGrid>
2

2 Answers

0
votes

I had this similar problem. Take a look at following page :

Silverlight DataBinding Error

0
votes

I'm updating my question with a solution to the problem. Hopefully this will help someone with the same issue.

I had to create a DataTemplateSelector class and then call said class in the XAML. Below is a copy of the new XAML code along with the Template Selector class.

<Window.Resources>
        <DataTemplate x:Key="ProviderStringTemplate" DataType="{x:Type System:String}">
            <TextBox VerticalAlignment="Center" Text="{Binding Value, Mode=TwoWay, UpdateSourceTrigger=LostFocus}" Width="200" />
        </DataTemplate>
        <DataTemplate x:Key="ProviderBooleanTemplate" DataType="{x:Type System:Boolean}">
            <CheckBox Margin="15,0,0,0" VerticalAlignment="Center" IsChecked="{Binding Value, Mode=TwoWay, UpdateSourceTrigger=LostFocus}" />
        </DataTemplate>
        <Windows:ProviderPropertyTemplateSelector x:Key="templateSelector" />
    </Window.Resources>    
<DataGrid AutoGenerateColumns="False" Name="dataGridProviderProperties" Height="215" FontSize="11" HorizontalGridLinesBrush="#FFC1C1C1" 
                            VerticalGridLinesBrush="#FFC1C1C1" Padding="0" Background="#00000000" HorizontalScrollBarVisibility="Auto" 
                              CanUserResizeRows="False" AlternationCount="2" AlternatingRowBackground="#05000000" CanUserAddRows="False" 
                              DataContext="{Binding}" ItemsSource="{Binding Properties}" VerticalAlignment="Center" Width="345" 
                            VerticalContentAlignment="Center" IsManipulationEnabled="False" CanUserReorderColumns="False" SelectionUnit="Cell">
                        <DataGrid.Columns>
                            <DataGridTemplateColumn Header="Key" Width="100">
                                <DataGridTemplateColumn.CellTemplate>
                                    <DataTemplate>
                                        <Label VerticalContentAlignment="Center" Height="27" VerticalAlignment="Center" Content="{Binding Key}" Padding="3"></Label>
                                    </DataTemplate>
                                </DataGridTemplateColumn.CellTemplate>
                            </DataGridTemplateColumn>
                            <DataGridTemplateColumn Header="Value" CellTemplateSelector="{StaticResource templateSelector}" CanUserSort="True" Width="200" />
                        </DataGrid.Columns>
                    </DataGrid>

    public class ProviderPropertyTemplateSelector : DataTemplateSelector
    {
        public override DataTemplate SelectTemplate(object item, DependencyObject container)
        {
            var property = item as Property<object>;

            if (property == null)
                return null;

            if (property.Value is Boolean)
                return ((FrameworkElement)container).FindResource("ProviderBooleanTemplate") as DataTemplate;

            if (property.Value is String || property.Value is int)
                return ((FrameworkElement)container).FindResource("ProviderStringTemplate") as DataTemplate;

            return null;
        }
    }