none
Datagrid, ComboBox and scroll issue (Silverlight 3)

    Question

  • Hi,

     After a lot of research, I didn't find any solution to my issue, even if a lot of people have meet this one.

    I have a DataGrid and in this one, a column with ComboBox. When I launch the application, all ComboBox SelectedItems are correct. But if I scroll the DataGrid, SelectedItems of ComboBox who had disappeared, have changes. (If I change manually the selectedItems of a ComboBox, this one keep always the same).

    <data:DataGridTemplateColumn Header="Catégorie">
                        <data:DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <ComboBox x:Name="Combox" ItemsSource="{Binding Source={StaticResource Questi}}" DisplayMemberPath="NOM_CATEGORY" SelectedItem="{Binding ElementName=Combox, Converter={StaticResource Ruru}}" Width="80"/>
                            </DataTemplate>
                        </data:DataGridTemplateColumn.CellTemplate>

    </data:DataGridTemplateColumn>

     

    "Questi" is a List. "Ruru" return a element of Questi.

    I have seen a lot of topics speeking about this, but with Silverlight 2 and I didn't find THE solution. Here I use Silverlight 3.

     

    I hope you could help me.

    Thanks

     

    (Sorry if my english is not so good)

    Friday, September 04, 2009 5:45 AM

Answers

  •  There is a solution in Silverlight 3 for this.

    Let's say you have combox declared in the DataGrid Cell template:

     
    <ComboBox Width="auto" 
    	ItemsSource="{Binding AnswersList, Mode=OneWay}" 
        SelectedItem="{Binding AnswerListItem, Mode=TwoWay}" 
        DisplayMemberPath="OptionText"
        />
     

     The problem is that during scrolling, DataGrid fires out RowLoading event, and re-initializes the ComboBoxes, and there is a bug that SelectedItem (TwoWay bound) property is set to NULL.

    My way out was to handle setting NULL in the ViewModel:

     

    public OptionItem AnswerListItem
            {
                get 
                { 
                    return _answerListItem; 
                }
                set 
                {
                    if (value != null)
                    {
                        _answerListItem = value;
                        NotifyPropertyChanged("AnswerListItem");
                    }
                }
            }

    And now  no NULL values are passed from the ComboBox, which keeps the selection on sorting or scrolling the datagrid.

    Let me know in case it works in your case.

     

    Friday, April 16, 2010 11:20 AM

All replies

  • hi, if 'ruru' is going to return only one elemnt why dont u give as selected item = binding ruru ??? try if thta works.. post back if that doesnt.. thanks
    Wednesday, November 11, 2009 1:41 PM
  •  Hi, the issue has been resolved by a totaly other way. Thanks for answer.

    Sunday, February 14, 2010 3:36 PM
  • How did you resolve it?  I'm having the same problem.

    Thanks.

    Friday, April 02, 2010 3:55 PM
  •   Hi,

     Like said  just before, I have totaly changed my design/fonctionnalities. So I didn't have resolved the issue. Maybe you can try with Silverlight 4 :)

    Monday, April 05, 2010 5:28 PM
  •  There is a solution in Silverlight 3 for this.

    Let's say you have combox declared in the DataGrid Cell template:

     
    <ComboBox Width="auto" 
    	ItemsSource="{Binding AnswersList, Mode=OneWay}" 
        SelectedItem="{Binding AnswerListItem, Mode=TwoWay}" 
        DisplayMemberPath="OptionText"
        />
     

     The problem is that during scrolling, DataGrid fires out RowLoading event, and re-initializes the ComboBoxes, and there is a bug that SelectedItem (TwoWay bound) property is set to NULL.

    My way out was to handle setting NULL in the ViewModel:

     

    public OptionItem AnswerListItem
            {
                get 
                { 
                    return _answerListItem; 
                }
                set 
                {
                    if (value != null)
                    {
                        _answerListItem = value;
                        NotifyPropertyChanged("AnswerListItem");
                    }
                }
            }

    And now  no NULL values are passed from the ComboBox, which keeps the selection on sorting or scrolling the datagrid.

    Let me know in case it works in your case.

     

    Friday, April 16, 2010 11:20 AM
  • Thanks!  Your solution worked for me.

    Tuesday, April 20, 2010 7:46 PM
  •  Unfortunately, this only works with SelectedItem.

    If you are using the new Silverlight 4 SelectedValue and SalectedValuePath, then all you can do is avoid the virtualization.  the only way I know of to do that is to;

    1) remove the height constriction of your datagrid, that way it won't display a scrollbar, and then

    2) enclose the datagrid in a <ScrollViewer>

    The ScrollViewer will no longer use virtualization, will get rid of jerky movements (better performance) and this problem just magically goes away. 

    If only there was a checkbox on the datagrid to turn off virtualization you wouldn't need to do this. Kind of klugy if you ask me.  Maybe Silverlight 5...

    Thursday, June 10, 2010 11:22 AM
  • hi,

    i using silverlight 4 and still having the same problem on datagrid scrolling and sorting, i tried to use your way above, but no luck still the same error. provided example codes below. program allow user specify combobox value for multiple record, then click one of the columns to sort. then the values in combobox missing.

    can you please assist me to check if anything missed out, i can send you the project files if needed, thanks in advance!

        <Grid x:Name="LayoutRoot" Background="White" Loaded="LayoutRoot_Loaded">
            <sdk:DataGrid Name="dg" AutoGenerateColumns="False" >
                <sdk:DataGrid.Columns>
                    <sdk:DataGridTextColumn Header="Record Id" Binding="{Binding RecordId,Mode=OneWay}"/>
                    <sdk:DataGridTextColumn Header="Record Date" Binding="{Binding RecordDate,Mode=OneWay}"/>
                    <sdk:DataGridTemplateColumn Header="Action">
                        <sdk:DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <ComboBox Name="cbActionList" ItemsSource="{Binding ActionItems,Mode=OneWay}" 
                                                        SelectedItem="{Binding Action,Mode=TwoWay}" 
                                                        DisplayMemberPath="Value">
                                </ComboBox>
                            </DataTemplate>
                        </sdk:DataGridTemplateColumn.CellTemplate>
                    </sdk:DataGridTemplateColumn>
                </sdk:DataGrid.Columns>
            </sdk:DataGrid>
        </Grid>
    
      public class ActionItem
      {
        public string Key
        {
          get;
          set;
        }
        public string Value
        {
          get;
          set;
        }
      }
    
      public class Record : INotifyPropertyChanged
      {
        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged(PropertyChangedEventArgs e)
        {
          if (PropertyChanged != null)
          {
            PropertyChanged(this, e);
          }
        }
    
        public string RecordId
        {
          get;
          set;
        }
        public DateTime RecordDate
        {
          get;
          set;
        }
    
        private ActionItem _Action;
        public ActionItem Action
        {
          get
          {
            return _Action;
          }
          set
          {
            if (value != null)
            {
              _Action = value;
              OnPropertyChanged(new PropertyChangedEventArgs("Action"));
            }
          }
        }
        public IList<ActionItem> ActionItems
        {
          get
          {
            IList<ActionItem> items = new List<ActionItem>();
            items.Add(new ActionItem()
            {
              Key = "A",
              Value="APPROVE"
            });
            items.Add(new ActionItem()
            {
              Key = "R",
              Value="REJECT"
            });
    
            return items;
          }
        }
      }
    

    
    
    Friday, August 19, 2011 10:09 AM
  • use following style to the datagrid,as i disabled the vertical scrollbar and wrapped the scrollviewer to the datagridrowpresenter
    <Style x:Key="ScrollViewerStyle1" TargetType="ScrollViewer">
    			<Setter Property="HorizontalContentAlignment" Value="Left"/>
    <Setter Property="VerticalContentAlignment" Value="Top"/>
    <Setter Property="VerticalScrollBarVisibility" Value="Visible"/>
    <Setter Property="Padding" Value="4"/>
    <Setter Property="BorderThickness" Value="1"/>
    <Setter Property="BorderBrush">
    <Setter.Value>
    <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
    <GradientStop Color="#FFA3AEB9" Offset="0"/>
    <GradientStop Color="#FF8399A9" Offset="0.375"/>
    <GradientStop Color="#FF718597" Offset="0.375"/>
    <GradientStop Color="#FF617584" Offset="1"/>
    </LinearGradientBrush>
    </Setter.Value>
    </Setter>
    <Setter Property="Template">
    <Setter.Value>
    <ControlTemplate TargetType="ScrollViewer">
    <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="2">
    <Grid Background="{TemplateBinding Background}">
    <Grid.RowDefinitions>
    <RowDefinition Height="*"/>
    <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
    <ColumnDefinition Width="*"/>
    <ColumnDefinition Width="Auto"/>
    </Grid.ColumnDefinitions>
    <ScrollContentPresenter x:Name="ScrollContentPresenter" Cursor="{TemplateBinding Cursor}" ContentTemplate="{TemplateBinding ContentTemplate}"/>
    <Rectangle Fill="#FFE9EEF4" Grid.Column="1" Grid.Row="1" Opacity="0"/>
    <ScrollBar x:Name="VerticalScrollBar" Margin="0,-1,-1,-1" Width="18" Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" IsTabStop="False" Grid.Column="1" Grid.Row="0" Maximum="{TemplateBinding ScrollableHeight}" Minimum="0" Value="{TemplateBinding VerticalOffset}" Orientation="Vertical" ViewportSize="{TemplateBinding ViewportHeight}"/>
    <ScrollBar x:Name="HorizontalScrollBar" Height="18" Margin="-1,0,-1,-1" Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" IsTabStop="False" Grid.Column="0" Grid.Row="1" Maximum="{TemplateBinding ScrollableWidth}" Minimum="0" Value="{TemplateBinding HorizontalOffset}" Orientation="Horizontal" ViewportSize="{TemplateBinding ViewportWidth}"/>
    </Grid>
    </Border>
    </ControlTemplate>
    </Setter.Value>
    </Setter>
    </Style>
    <Style x:Key="VertualizedDataGridStyle" TargetType="data:DataGrid">
    <Setter Property="RowBackground" Value="#AAEAEFF4"/>
    <Setter Property="AlternatingRowBackground" Value="#00FFFFFF"/>
    <Setter Property="Background" Value="#FFFFFFFF"/>
    <Setter Property="HeadersVisibility" Value="Column"/>
    <Setter Property="HorizontalScrollBarVisibility" Value="Disabled"/>
    <Setter Property="VerticalScrollBarVisibility" Value="Disabled"/>
    <Setter Property="SelectionMode" Value="Extended"/>
    <Setter Property="CanUserReorderColumns" Value="True"/>
    <Setter Property="CanUserResizeColumns" Value="True"/>
    <Setter Property="CanUserSortColumns" Value="True"/>
    <Setter Property="AutoGenerateColumns" Value="True"/>
    <Setter Property="RowDetailsVisibilityMode" Value="VisibleWhenSelected"/>
    <Setter Property="BorderBrush">
    <Setter.Value>
    <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
    <GradientStop Color="#FFA3AEB9" Offset="0"/>
    <GradientStop Color="#FF8399A9" Offset="0.375"/>
    <GradientStop Color="#FF718597" Offset="0.375"/>
    <GradientStop Color="#FF617584" Offset="1"/>
    </LinearGradientBrush>
    </Setter.Value>
    </Setter>
    <Setter Property="BorderThickness" Value="1"/>
    <Setter Property="DragIndicatorStyle">
    <Setter.Value>
    <Style TargetType="ContentControl">
    <Setter Property="Foreground" Value="#7FFFFFFF"/>
    <Setter Property="Template">
    <Setter.Value>
    <ControlTemplate TargetType="ContentControl">
    <Grid>
    <VisualStateManager.VisualStateGroups>
    <VisualStateGroup x:Name="SortStates">
    <VisualState x:Name="Unsorted"/>
    <VisualState x:Name="SortAscending">
    <Storyboard>
    <DoubleAnimation Duration="0" Storyboard.TargetName="SortIcon" Storyboard.TargetProperty="Opacity" To="1.0"/>
    </Storyboard>
    </VisualState>
    <VisualState x:Name="SortDescending">
    <Storyboard>
    <DoubleAnimation Duration="0" Storyboard.TargetName="SortIcon" Storyboard.TargetProperty="Opacity" To="1.0"/>
    <DoubleAnimation Duration="0" Storyboard.TargetName="SortIcon" Storyboard.TargetProperty="(RenderTransform).ScaleY" To="-.9"/>
    </Storyboard>
    </VisualState>
    </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
    <Rectangle x:Name="BackgroundRectangle" Fill="#66808080" Stretch="Fill" Grid.ColumnSpan="2"/>
    <Rectangle x:Name="BackgroundGradient" Stretch="Fill" Opacity="0" Grid.ColumnSpan="2">
    <Rectangle.Fill>
    <LinearGradientBrush EndPoint=".7,1" StartPoint=".7,0">
    <GradientStop Color="#FFFFFFFF" Offset="0.015"/>
    <GradientStop Color="#F9FFFFFF" Offset="0.375"/>
    <GradientStop Color="#E5FFFFFF" Offset="0.6"/>
    <GradientStop Color="#C6FFFFFF" Offset="1"/>
    </LinearGradientBrush>
    </Rectangle.Fill>
    </Rectangle>
    <Grid HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
    <Grid.ColumnDefinitions>
    <ColumnDefinition/>
    <ColumnDefinition Width="Auto"/>
    </Grid.ColumnDefinitions>
    <ContentPresenter Content="{TemplateBinding Content}"/>
    <Path x:Name="SortIcon" Fill="#7FFFFFFF" Stretch="Uniform" HorizontalAlignment="Left" Margin="4,0,0,0" VerticalAlignment="Center" Width="8" Opacity="0" RenderTransformOrigin=".5,.5" Grid.Column="1" Data="F1 M -5.215,6.099L 5.215,6.099L 0,0L -5.215,6.099 Z ">
    <Path.RenderTransform>
    <ScaleTransform ScaleX=".9" ScaleY=".9"/>
    </Path.RenderTransform>
    </Path>
    </Grid>
    </Grid>
    </ControlTemplate>
    </Setter.Value>
    </Setter>
    </Style>
    </Setter.Value>
    </Setter>
    <Setter Property="DropLocationIndicatorStyle">
    <Setter.Value>
    <Style TargetType="ContentControl">
    <Setter Property="Background" Value="#FF3F4346"/>
    <Setter Property="Width" Value="2"/>
    <Setter Property="Template">
    <Setter.Value>
    <ControlTemplate TargetType="ContentControl">
    <Rectangle Fill="{TemplateBinding Background}" Height="{TemplateBinding Height}" Width="{TemplateBinding Width}"/>
    </ControlTemplate>
    </Setter.Value>
    </Setter>
    </Style>
    </Setter.Value>
    </Setter>
    <Setter Property="GridLinesVisibility" Value="Vertical"/>
    <Setter Property="HorizontalGridLinesBrush" Value="#FFC9CACA"/>
    <Setter Property="IsTabStop" Value="True"/>
    <Setter Property="VerticalGridLinesBrush" Value="#FFC9CACA"/>
    <Setter Property="Template">
    <Setter.Value>
    <ControlTemplate TargetType="data:DataGrid">
    <Grid>
    <VisualStateManager.VisualStateGroups>
    <VisualStateGroup x:Name="CommonStates">
    <VisualState x:Name="Normal"/>
    <VisualState x:Name="Disabled">
    <Storyboard>
    <DoubleAnimation Duration="0" Storyboard.TargetName="DisabledVisualElement" Storyboard.TargetProperty="Opacity" To="1"/>
    </Storyboard>
    </VisualState>
    </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
    <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="2">
    <Grid x:Name="Root" Background="{TemplateBinding Background}">
    <Grid.Resources>
    <ControlTemplate x:Key="TopLeftHeaderTemplate" TargetType="dataPrimitives:DataGridColumnHeader">
    <Grid x:Name="Root">
    <Grid.RowDefinitions>
    <RowDefinition/>
    <RowDefinition/>
    <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    <Border Grid.RowSpan="2" Background="#FF1F3B53" BorderBrush="#FFC9CACA" BorderThickness="0,0,1,0">
    <Rectangle Stretch="Fill" StrokeThickness="1">
    <Rectangle.Fill>
    <LinearGradientBrush EndPoint=".7,1" StartPoint=".7,0">
    <GradientStop Color="#FCFFFFFF" Offset="0.015"/>
    <GradientStop Color="#F7FFFFFF" Offset="0.375"/>
    <GradientStop Color="#E5FFFFFF" Offset="0.6"/>
    <GradientStop Color="#D1FFFFFF" Offset="1"/>
    </LinearGradientBrush>
    </Rectangle.Fill>
    </Rectangle>
    </Border>
    <Rectangle Fill="#FFDBDCDC" StrokeThickness="1" Height="1" VerticalAlignment="Bottom" Width="Auto" Grid.RowSpan="2"/>
    </Grid>
    </ControlTemplate>
    <ControlTemplate x:Key="TopRightHeaderTemplate" TargetType="dataPrimitives:DataGridColumnHeader">
    <Grid x:Name="RootElement">
    <Grid.RowDefinitions>
    <RowDefinition/>
    <RowDefinition/>
    <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    <Border Grid.RowSpan="2" Background="#FF1F3B53" BorderBrush="#FFC9CACA" BorderThickness="1,0,0,0">
    <Rectangle Stretch="Fill">
    <Rectangle.Fill>
    <LinearGradientBrush EndPoint=".7,1" StartPoint=".7,0">
    <GradientStop Color="#FCFFFFFF" Offset="0.015"/>
    <GradientStop Color="#F7FFFFFF" Offset="0.375"/>
    <GradientStop Color="#E5FFFFFF" Offset="0.6"/>
    <GradientStop Color="#D1FFFFFF" Offset="1"/>
    </LinearGradientBrush>
    </Rectangle.Fill>
    </Rectangle>
    </Border>
    </Grid>
    </ControlTemplate>
    </Grid.Resources>
    <Grid.RowDefinitions>
    <RowDefinition Height="Auto"/>
    <RowDefinition/>
    <RowDefinition Height="Auto"/>
    <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
    <ColumnDefinition Width="Auto"/>
    <ColumnDefinition/>
    <ColumnDefinition Width="Auto"/>
    </Grid.ColumnDefinitions>
    <dataPrimitives:DataGridColumnHeader x:Name="TopLeftCornerHeader" Width="22" Template="{StaticResource TopLeftHeaderTemplate}"/>
    <dataPrimitives:DataGridColumnHeadersPresenter x:Name="ColumnHeadersPresenter" Grid.Column="1"/>
    <dataPrimitives:DataGridColumnHeader x:Name="TopRightCornerHeader" Template="{StaticResource TopRightHeaderTemplate}" Grid.Column="2"/>
    <Rectangle x:Name="ColumnHeadersAndRowsSeparator" Fill="#FFC9CACA" StrokeThickness="1" Height="1" VerticalAlignment="Bottom" Width="Auto" Grid.ColumnSpan="3"/>
    <ScrollViewer Style="{StaticResource ScrollViewerStyle1}" Grid.ColumnSpan="2" Grid.Row="1">
    <dataPrimitives:DataGridRowsPresenter x:Name="RowsPresenter" Height="Auto" Width="Auto"/>
    </ScrollViewer>
    <Rectangle x:Name="BottomRightCorner" Fill="#FFE9EEF4" Grid.Column="2" Grid.Row="2"/>
    <Rectangle x:Name="BottomLeftCorner" Fill="#FFE9EEF4" Grid.ColumnSpan="2" Grid.Row="2"/>
    <ScrollBar x:Name="VerticalScrollbar" Margin="0,-1,-1,-1" Width="18" Grid.Column="2" Grid.Row="1" Orientation="Vertical"/>

    <Grid Grid.Column="1" Grid.Row="2">
    <Grid.ColumnDefinitions>
    <ColumnDefinition Width="Auto"/>
    <ColumnDefinition/>
    </Grid.ColumnDefinitions>
    <Rectangle x:Name="FrozenColumnScrollBarSpacer"/>
    <ScrollBar x:Name="HorizontalScrollbar" Height="18" Margin="-1,0,-1,-1" Grid.Column="1" Orientation="Horizontal"/>
    </Grid>
    <dataInput:ValidationSummary x:Name="ValidationSummary" MaxHeight="90" Grid.ColumnSpan="3" Grid.Row="3" Filter="ObjectErrors"/>
    </Grid>
    </Border>
    <Border x:Name="DisabledVisualElement" Height="Auto" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Width="Auto" IsHitTestVisible="False" Opacity="0" Background="#8CFFFFFF" CornerRadius="2"/>
    </Grid>
    </ControlTemplate>
    </Setter.Value>
    </Setter>
    </Style>
    Tuesday, October 11, 2011 3:48 AM
  • It is due to virtualization usage by Silverlight.

    I came across this problem when you scroll, data within the grid changes in terms of display. But in actuality it is the same. It is just a fact that on UI, silverlight shows it incorrectly because it uses the same controls while rendering.

    The best way is to handle your logic inside LoadingRow and UnloadingRow events of the datagarid.

    I have some detail posted on the following link:

    http://stackoverflow.com/a/25566163/3989725

    Friday, August 29, 2014 10:30 AM