Silverlight- DataGrid control - Selection Changed event interfering with sorting
-
09-06-2019 - |
Question
I'm currently playing with the Silverlight(Beta 2) Datagrid control. Before I wired up the SelectionChanged event, the grid would sort perfectly by clicking on the header. Now, when the grid is clicked, it will fire the SelectionChanged event when I click the header to sort. Is there any way around this?
In a semi-related topic, I'd like to have the SelectionChanged event fire when I click on an already selected item (so that I can have a pop-up occur to allow the user to edit the selected value). Right now, you have to click on a different value and then back to the value you wanted in order for it to pop up. Is there another way?
Included is my code.
The Page:
<UserControl x:Class="WebServicesApp.Page"
xmlns="http://schemas.microsoft.com/client/2007"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"
Width="1280" Height="1024" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d">
<Grid x:Name="LayoutRoot" Background="White">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" x:Name="OurStack" Orientation="Vertical" Margin="5,5,5,5">
<ContentControl VerticalAlignment="Center" HorizontalAlignment="Center">
<StackPanel x:Name="SearchStackPanel" Orientation="Horizontal" Margin="5,5,5,5">
<TextBlock x:Name="SearchEmail" HorizontalAlignment="Stretch" VerticalAlignment="Center" Text="Email Address:" Margin="5,5,5,5" />
<TextBox x:Name="InputText" HorizontalAlignment="Stretch" VerticalAlignment="Center" Width="150" Height="Auto" Margin="5,5,5,5"/>
<Button x:Name="SearchButton" Content="Search" Click="CallServiceButton_Click" HorizontalAlignment="Center" VerticalAlignment="Center" Width="75" Height="Auto" Background="#FFAFAFAF" Margin="5,5,5,5"/>
</StackPanel>
</ContentControl>
<Grid x:Name="DisplayRoot" Background="White" ShowGridLines="True"
HorizontalAlignment="Center" VerticalAlignment="Center" MaxHeight="300" MinHeight="100" MaxWidth="800" MinWidth="200"
ScrollViewer.HorizontalScrollBarVisibility="Visible" ScrollViewer.VerticalScrollBarVisibility="Visible">
<data:DataGrid ItemsSource="{Binding ''}" CanUserReorderColumns="False" CanUserResizeColumns="False"
AutoGenerateColumns="False" AlternatingRowBackground="#FFAFAFAF" SelectionMode="Single"
HorizontalAlignment="Center" VerticalAlignment="Center" Margin="5,5,5,5" x:Name="IncidentGrid" SelectionChanged="IncidentGrid_SelectionChanged">
<data:DataGrid.Columns>
<data:DataGridTextColumn DisplayMemberBinding="{Binding Address}" Header="Email Address" IsReadOnly="True" /> <!--Width="150"-->
<data:DataGridTextColumn DisplayMemberBinding="{Binding whereClause}" Header="Where Clause" IsReadOnly="True" /> <!--Width="500"-->
<data:DataGridTextColumn DisplayMemberBinding="{Binding Enabled}" Header="Enabled" IsReadOnly="True" />
</data:DataGrid.Columns>
</data:DataGrid>
</Grid>
</StackPanel>
<Grid x:Name="EditPersonPopupGrid" Visibility="Collapsed">
<Rectangle HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Opacity="0.765" Fill="#FF8A8A8A" />
<Border CornerRadius="30" Background="#FF2D1DCC" Width="700" Height="400" HorizontalAlignment="Center" VerticalAlignment="Center" BorderThickness="1,1,1,1" BorderBrush="#FF000000">
<StackPanel x:Name="EditPersonStackPanel" Orientation="Vertical" Background="White" HorizontalAlignment="Center" VerticalAlignment="Center" Width="650" >
<ContentControl>
<StackPanel x:Name="EmailEditStackPanel" Orientation="Horizontal">
<TextBlock Text="Email Address:" Width="200" Margin="5,0,5,0" />
<TextBox x:Name="EmailPopupTextBox" Width="200" />
</StackPanel>
</ContentControl>
<ContentControl>
<StackPanel x:Name="AppliesToDropdownStackPanel" Orientation="Horizontal" Margin="2,2,2,0">
<TextBlock Text="Don't send when update was done by:" />
<StackPanel Orientation="Vertical" MaxHeight="275" MaxWidth="350" >
<TextBlock x:Name="SelectedItemTextBlock" TextAlignment="Right" Width="200" Margin="5,0,5,0" />
<Grid x:Name="UserDropDownGrid" MaxHeight="75" MaxWidth="200" Visibility="Collapsed" ScrollViewer.VerticalScrollBarVisibility="Visible" ScrollViewer.HorizontalScrollBarVisibility="Hidden" >
<Rectangle Fill="White" />
<Border Background="White">
<ListBox x:Name="UsersListBox" SelectionChanged="UsersListBox_SelectionChanged" ItemsSource="{Binding UserID}" />
</Border>
</Grid>
</StackPanel>
<Button x:Name="DropDownButton" Click="DropDownButton_Click" VerticalAlignment="Top" Width="25" Height="25">
<Path Height="10" Width="10" Fill="#FF000000" Stretch="Fill" Stroke="#FF000000" Data="M514.66669,354 L542.16669,354 L527.74988,368.41684 z" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="1,1,1,1"/>
</Button>
</StackPanel>
</ContentControl>
<TextBlock Text="Where Clause Condition:" />
<TextBox x:Name="WhereClauseTextBox" Height="200" Width="800" AcceptsReturn="True" TextWrapping="Wrap" />
<ContentControl>
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<Button x:Name="TestConditionButton" Content="Test Condition" Margin="5,5,5,5" Click="TestConditionButton_Click" />
<Button x:Name="Save" Content="Save" HorizontalAlignment="Right" Margin="5,5,5,5" Click="Save_Click" />
<Button x:Name="Cancel" Content="Cancel" HorizontalAlignment="Right" Margin="5,5,5,5" Click="Cancel_Click" />
</StackPanel>
<TextBlock x:Name="TestContitionResults" Visibility="Collapsed" />
</StackPanel>
</ContentControl>
</StackPanel>
</Border>
</Grid>
</Grid>
And the call that occurs when the grid's selection is changed:
Private Sub IncidentGrid_SelectionChanged(ByVal sender As System.Object, ByVal e As System.EventArgs)
If mFirstTime Then
mFirstTime = False
Else
Dim data As SimpleASMX.EMailMonitor = CType(IncidentGrid.SelectedItem, SimpleASMX.EMailMonitor)
Dim selectedGridItem As SimpleASMX.EMailMonitor = Nothing
If IncidentGrid.SelectedItem IsNot Nothing Then
selectedGridItem = CType(IncidentGrid.SelectedItem, SimpleASMX.EMailMonitor)
EmailPopupTextBox.Text = selectedGridItem.Address
SelectedItemTextBlock.Text = selectedGridItem.AppliesToUserID
WhereClauseTextBox.Text = selectedGridItem.whereClause
IncidentGrid.SelectedIndex = mEmailMonitorData.IndexOf(selectedGridItem)
End If
If IncidentGrid.SelectedIndex > -1 Then
EditPersonPopupGrid.Visibility = Windows.Visibility.Visible
Else
EditPersonPopupGrid.Visibility = Windows.Visibility.Collapsed
End If
End If
End Sub
Sorry if my code is atrocious, I'm still learning Silverlight.
Solution
That looks like a Silverlight bug to me. I've just tried it and what's happening on my end is that the SelectionChanged event fires twice when you click the column header and to make matters worse, the index of the selected item doesn't stay synched with the currently selected item.
I'd suggest you work your way around it by using the knowledge that the first time SelectionChanged fires, the value of the datagrid's SelectedItem property will be null
Here's some sample code that at least lives with the issue. Your SelectionChanged logic can go in the if clause.
public partial class Page : UserControl
{
private Person _currentSelectedPerson;
public Page()
{
InitializeComponent();
List<Person> persons = new List<Person>();
persons.Add(new Person() { Age = 5, Name = "Tom" });
persons.Add(new Person() { Age = 3, Name = "Lisa" });
persons.Add(new Person() { Age = 4, Name = "Sam" });
dg.ItemsSource = persons;
}
private void SelectionChanged(object sender, EventArgs e)
{
DataGrid grid = sender as DataGrid;
if (grid.SelectedItem != null)
{
_currentSelectedPerson = grid.SelectedItem as Person;
}
else
{
grid.SelectedItem = _currentSelectedPerson;
}
}
}
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
OTHER TIPS
Frozen Columns in Silverlight DataGrid..
http://dotnetdreamer.wordpress.com/2009/01/31/silverlight-2-datagrid-frozen-columns/
There's a bugfix for the first issue you mentioned (selection changed event getting fired on resort).
See the following URL for Microsoft's patch:
This worked, but now if I sort twice, on the first one it sorts, and then does the popup as the first selected item of the grid . If I close the popup grid, and then try to sort a second time, it stack overflows, and crashes firefox out.
I'm thinking I may need to rethink working in silverlight until the system gets a bit more stable.
Thanks for the answer Hovito!