在DevExpress中使用GridControl,其中有一列需要使用RadioButton,有两个问题,一是RadioButton的数据绑定问题,详见上一篇文章,二是在选中RadioButton后,如果滚动滚动条,选中状态就会丢失,原因在于整个GridControl使用一个渲染器,为了效率考虑,每次只渲染5行,当滚动滚动条的时候,下面行的数据也是使用的同一个渲染器,所以数据就会被冲掉。在使用WPF自带的DataGrid也会有这样的问题,DevExpress的论坛上说暂时无法解决该Bug。我们可以采用其他途径来解决。
问题代码:
xmlns:dxg="http://schemas.devexpress.com/winfx/2008/xaml/grid"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
<dxg:GridControl Name="datagrid" AutoGenerateColumns="None" ShowBorder="False" CurrentItem="{Binding CurrentItem,Mode=TwoWay}" SelectedItem="{Binding SelectedItem,Mode=TwoWay}"
ItemsSource="{Binding Students}" Height="2000">
<dxg:GridControl.View>
<dxg:TableView AutoWidth="True" AllowEditing="True" VerticalScrollbarVisibility="Hidden"/>
</dxg:GridControl.View>
<dxg:GridControl.Columns>
<dxg:GridColumn Header="学号" Binding="{Binding Sid,Mode=TwoWay}"/>
<dxg:GridColumn Header="姓名" Binding="{Binding Sname,Mode=TwoWay}"/>
<dxg:GridColumn Header="状态">
<dxg:GridColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<StackPanel Orientation="Horizontal">
<RadioButton Content="早退" IsChecked="{Binding RowData.Row.IsLeaved,Mode=TwoWay}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Checked">
<i:InvokeCommandAction Command="{Binding ElementName=dockPanel,Path=DataContext.LeavedCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</RadioButton>
<RadioButton Content="正常" IsChecked="{Binding RowData.Row.IsRight,Mode=TwoWay}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Checked">
<i:InvokeCommandAction Command="{Binding ElementName=dockPanel,Path=DataContext.RightCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</RadioButton>
</StackPanel>
</StackPanel>
</DataTemplate>
</dxg:GridColumn.CellTemplate>
</dxg:GridColumn>
</dxg:GridControl.Columns>
</dxg:GridControl>
解决方案:
在该GridControl的外层再套一个ScrollViewer,然后禁用GridControl的VerticalScrollBar,设置GridControl的给定高度。这样拉动滚动条里面的内容不会重新渲染,数据也就不会丢失了。然而带来的问题是,滚动后标题行也会滚动,看下面的时候就看不见标题行了,此问题暂未解决;通过后台代码设置选中行后自动滚动到选中行,代码及解决方案如下:
设置外层ScrollViewer CanContentScroll="True",然后在后台设置焦点grid.View.Focus();
<ScrollViewer CanContentScroll="True">
<dxg:GridControl Name="datagrid" AutoGenerateColumns="None" ShowBorder="False" CurrentItem="{Binding CurrentItem,Mode=TwoWay}" SelectedItem="{Binding SelectedItem,Mode=TwoWay}"
ItemsSource="{Binding Students}" Height="2000">
<dxg:GridControl.View>
<dxg:TableView AutoWidth="True" AllowEditing="True" VerticalScrollbarVisibility="Hidden"/>
</dxg:GridControl.View>
<dxg:GridControl.Columns>
<dxg:GridColumn Header="学号" Binding="{Binding Sid,Mode=TwoWay}"/>
<dxg:GridColumn Header="姓名" Binding="{Binding Sname,Mode=TwoWay}"/>
<dxg:GridColumn Header="状态">
<dxg:GridColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Visibility="{Binding ElementName=dockPanel,Path=DataContext.AfterItemsVisibility,Mode=TwoWay}">
<RadioButton Content="早退" IsChecked="{Binding RowData.Row.IsLeaved,Mode=TwoWay}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Checked">
<i:InvokeCommandAction Command="{Binding ElementName=dockPanel,Path=DataContext.LeavedCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</RadioButton>
<RadioButton Content="正常" IsChecked="{Binding RowData.Row.IsRight,Mode=TwoWay}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Checked">
<i:InvokeCommandAction Command="{Binding ElementName=dockPanel,Path=DataContext.RightCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</RadioButton>
</StackPanel>
</DataTemplate>
</dxg:GridColumn.CellTemplate>
</dxg:GridColumn>
</dxg:GridControl.Columns>
</dxg:GridControl>
</ScrollViewer>