Silverlight- DataGrid 控件 - 选择更改事件干扰排序

Posted

技术标签:

【中文标题】Silverlight- DataGrid 控件 - 选择更改事件干扰排序【英文标题】:Silverlight- DataGrid control - Selection Changed event interfering with sorting 【发布时间】:2010-09-09 14:55:59 【问题描述】:

我目前正在使用 Silverlight(Beta 2) Datagrid 控件。在我连接 SelectionChanged 事件之前,通过单击标题,网格将完美排序。现在,当单击网格时,当我单击标题进行排序时,它将触发 SelectionChanged 事件。有没有办法解决这个问题?

在一个半相关的主题中,我希望在单击已选择的项目时触发 SelectionChanged 事件(这样我可以弹出一个窗口以允许用户编辑选定的值)。现在,您必须单击一个不同的值,然后返回到您想要的值才能弹出它。还有其他方法吗?

包括我的代码。

页面:

<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>

当网格的选择改变时发生的调用:

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

对不起,如果我的代码很糟糕,我还在学习 Silverlight。

【问题讨论】:

【参考方案1】:

在我看来,这就像一个 Silverlight 错误。我刚刚尝试过,最终发生的情况是,当您单击列标题时 SelectionChanged 事件会触发两次,更糟糕的是,所选项目的索引不会与当前选中的项目。

我建议您通过使用第一次触发 SelectionChanged 时数据网格的 SelectedItem 属性的值将是 null

这里有一些示例代码,至少可以解决这个问题。您的 SelectionChanged 逻辑可以放在 if 子句中。

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; 

【讨论】:

【参考方案2】:

Silverlight DataGrid 中的冻结列..

http://dotnetdreamer.wordpress.com/2009/01/31/silverlight-2-datagrid-frozen-columns/

【讨论】:

【参考方案3】:

您提到的第一个问题有一个错误修复(选择更改事件在度假时被触发)。

微软的补丁见以下网址:

http://www.microsoft.com/downloads/details.aspx?familyid=084A1BB2-0078-4009-94EE-E659C6409DB0&displaylang=en

【讨论】:

【参考方案4】:

这行得通,但现在如果我排序两次,第一次排序,然后弹出作为 grid 的第一个选定项目。如果我关闭弹出网格,然后再次尝试排序,它会堆栈溢出,并使 firefox 崩溃。

我想我可能需要重新考虑在 Silverlight 中工作,直到系统变得更加稳定为止。

感谢霍维托的回答!

【讨论】:

以上是关于Silverlight- DataGrid 控件 - 选择更改事件干扰排序的主要内容,如果未能解决你的问题,请参考以下文章

Silverlight:如何访问 DataGrid RowDetailTemplate 中的控件

Silverlight 2 DataGrid December 2008

具有许多加载控件的 Silverlight 性能

Silverlight Combobox 将所选项目设置为 datagrid 的所选项目

增加 Silverlight DataGrid 中的列宽以填充整个 DG 宽度

在 Silverlight DataGrid 中设置初始排序顺序?