DataGridTemplateColumn 中的复选框有问题

Problem with checkbox in DataGridTemplateColumn

我需要帮助来完成我的第一个小应用程序。我正在尝试对数据网格中选中的行执行操作。

xaml :

                <DataGrid x:Name="dgConnected_Users" AutoGenerateColumns="False" IsReadOnly="True" Height="180" Background="Azure" ScrollViewer.CanContentScroll="True" FontSize="11" BorderBrush="#26BFF0" ScrollViewer.HorizontalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Disabled" BorderThickness="2,2,2,2" HeadersVisibility="Column" CanUserAddRows="False" CanUserDeleteRows="False" CanUserResizeRows="False" RowHeight="20" RowBackground="Azure" GridLinesVisibility="Horizontal" HorizontalGridLinesBrush="DarkOrange" Margin="10,0,10,0">
                <DataGrid.Columns>
                    <DataGridTextColumn x:Name="UID_UserName" FontFamily="Segoe UI Bold" Binding="{Binding UID_UserName}" Header="Utilisateur" Width="1*">
                        <DataGridTextColumn.ElementStyle>
                            <Style TargetType="TextBlock">
                                <Setter Property="VerticalAlignment" Value="Center"></Setter>
                                <Setter Property="Margin" Value="5,0"></Setter>
                            </Style>
                        </DataGridTextColumn.ElementStyle>
                    </DataGridTextColumn>
                    <DataGridTextColumn x:Name="UID_ComputerName" Binding="{Binding UID_ComputerName}" Header="Machine" Width="1*">
                        <DataGridTextColumn.ElementStyle>
                            <Style TargetType="TextBlock">
                                <Setter Property="VerticalAlignment" Value="Center"></Setter>
                                <Setter Property="Margin" Value="5,0"></Setter>
                            </Style>
                        </DataGridTextColumn.ElementStyle>
                    </DataGridTextColumn>
                    <DataGridTemplateColumn x:Name="UID_Chkbox" Width="24">
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <TextBlock TextAlignment="Center" VerticalAlignment="Center"><CheckBox x:Name="Chk_UID_IsSelected" IsChecked="{Binding IsChecked, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" Checked="Chk_UID_IsSelected_Checked" Unchecked="Chk_UID_IsSelected_Unchecked" Click="Chk_UID_IsSelected_Click"/></TextBlock>
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                        <DataGridTemplateColumn.Header>
                            <Image Source="components/resources/images/delete-24.png" Height="12" Width="12" StretchDirection="Both" Stretch="Fill"/>
                        </DataGridTemplateColumn.Header>
                    </DataGridTemplateColumn>
                </DataGrid.Columns>
            </DataGrid>
            <StackPanel Margin="10,10">
                <Button x:Name="UID_Disconnect" Width="270" Click="UID_Disconnect_Click">Déconnecter le(s) utilisateur(s)</Button>
            </StackPanel>
            <StackPanel Margin="10,0">
                <Grid>
                    <Border BorderBrush="#26BFF0" BorderThickness="0,1,0,0">
                        <TextBlock HorizontalAlignment="Center" FontFamily="Segoe UI Light" FontSize="10" Padding="5" Foreground="#FF4C4F54">InovaGes SAS · Développé par Fabrice BERTRAND</TextBlock>
                    </Border>
                </Grid>
            </StackPanel>

xaml.cs :

    private void UID_Disconnect_Click(object sender, RoutedEventArgs e)
    {
        /// gestion de la déconnexion des utilisateurs au clic du bouton 'UID_Disconnect'
        /// 
        IEnumerable<CheckBox> UsersInDatabase = dgConnected_Users.Items.OfType<CheckBox>().Where(usr => usr.IsChecked == true);

        foreach (CheckBox usr in UsersInDatabase)
        {

            MessageBox.Show("yeah"); /// do stuff here
        }
    }

我现在正在使用 MessageBox 测试代码。但什么也没有发生。帮助我完成项目的想法?

事实上,我需要为选中复选框的每一行获取 UID_UserName 执行 sql 删除。

我也尝试过使用 DataRowView。我可以获得 TextColumn,但没有复选框。

编辑 1 :

我认为部分问题是由于带有复选框的列不在 dt 中:

        private void refresh_Click(object sender, RoutedEventArgs e)
    {
        try
        {
            if (Cnx.State == System.Data.ConnectionState.Open)
            {
                Cnx.Close();
            }
            if (cmbAuthentification.Text.Equals("Windows"))
            {
                SQL_Connection.ConnectionString = @"Server = " + txtServerName.Text + "; Integrated Security = SSPI;";
                Cnx.ConnectionString = SQL_Connection.ConnectionString;
            }
            else if (cmbAuthentification.Text.Equals("SQL Server"))
            {
                SQL_Connection.ConnectionString = @"Server = " + txtServerName.Text + "; User ID =" + txtUserID.Text + "; Password=" + txtUserPwd.Password + ";";
                Cnx.ConnectionString = SQL_Connection.ConnectionString;
            }
            Cnx.Open();
            Cmd.Connection = Cnx;
            Cmd.CommandText = ("USE \"" + cmbDatabase.Text + "\";SELECT DISTINCT b.nt_username AS [UID_UserName], b.hostname AS [UID_ComputerName] FROM cbUserSession a INNER JOIN master..sysprocesses b ON a.cbSession = b.spid WHERE a.cbUserName IS NOT NULL;");
            SqlDataAdapter da = new SqlDataAdapter(Cmd);
            dt = new DataTable("Connected_Users");
            da.Fill(dt);
            /// dt.Columns.Add(new DataColumn("IsChecked", typeof(bool))); <-- maybe need to do something like that ?
            dgConnected_Users.ItemsSource = dt.DefaultView;
            Cnx.Close();
        }
        catch (Exception exception)
        {
            MessageBox.Show("Erreur de chargement des données pour le motif suivant : \n" + exception.Message, "OOoopssss !!!", MessageBoxButton.OK, MessageBoxImage.Error);
        }
    }

为了向您展示工作副本,我构建了其余代码。

我假设您有一个 class 对象,您将其作为项目源绑定到数据网格。 仅供参考,我创建了自己的 class 对象。请参阅下文并根据您的 class 文件进行更改。

步骤 1 - Class 创建

public class DataGridUser
{
    public string UID_UserName { get; set; }

    public string UID_ComputerName { get; set; }

    public bool IsChecked { get; set; }
}

第 2 步 - 单击按钮时,我只是修改了如下代码。

private void UID_Disconnect_OnClick(object sender, RoutedEventArgs e)
    {
        var selectedItems = dgConnected_Users.Items.Cast<DataGridUser>().Where(x => x.IsChecked);

        foreach (var item in selectedItems)
        {
            MessageBox.Show(item.UID_ComputerName + " " + item.UID_UserName);
        }
    }

在上面的代码中,我使用了“Cast”类型并将项目转换为数据网格绑定到的类型 DataGridUser(在本例中)。

其余代码与您的相同。

编辑 添加了代码来回答您的评论。

第 3 步 我复制了您的事件处理程序,然后稍作修改。请仔细比较代码和阅读注释,然后在您的程序中使用它。

private void refresh_Click(object sender, RoutedEventArgs e)
{
    try
    {
        if (Cnx.State == System.Data.ConnectionState.Open)
        {
            Cnx.Close();
        }
        if (cmbAuthentification.Text.Equals("Windows"))
        {
            SQL_Connection.ConnectionString = @"Server = " + txtServerName.Text + "; Integrated Security = SSPI;";
            Cnx.ConnectionString = SQL_Connection.ConnectionString;
        }
        else if (cmbAuthentification.Text.Equals("SQL Server"))
        {
            SQL_Connection.ConnectionString = @"Server = " + txtServerName.Text + "; User ID =" + txtUserID.Text + "; Password=" + txtUserPwd.Password + ";";
            Cnx.ConnectionString = SQL_Connection.ConnectionString;
        }
        Cnx.Open();
        Cmd.Connection = Cnx;
        Cmd.CommandText = ("USE \"" + cmbDatabase.Text + "\";SELECT DISTINCT b.nt_username AS [UID_UserName], b.hostname AS [UID_ComputerName] FROM cbUserSession a INNER JOIN master..sysprocesses b ON a.cbSession = b.spid WHERE a.cbUserName IS NOT NULL;");
        
        //SqlDataAdapter da = new SqlDataAdapter(Cmd);
        //dt = new DataTable("Connected_Users");
        //da.Fill(dt);
        // dt.Columns.Add(new DataColumn("IsChecked", typeof(bool))); <-- maybe need to do something like that ?

        // GK - Instead of using SqlDataAdapter. Use DataReader and transfer the data from DataReader to an object. See below.
            SqlDataReader reader = Cmd.ExecuteReader();
            var dataGridUserCollection = new List<DataGridUser>();

            if (reader.HasRows)
            {
                while (reader.Read())
                {
                    var currentDataGridUser = new DataGridUser()
                    {
                        UID_UserName = reader["UID_UserName"].ToString(),
                        UID_ComputerName = reader["UID_ComputerName"].ToString()
                    };

                    dataGridUserCollection.Add(currentDataGridUser);
                }
            }

            // GK - Bind new list object to DataGrid.
            // GK - Now the object bound to DataGrid is of type DataGridUser.
            // GK - So now when you do the type casting to DataGridUser on your button click
            // it won't throw any more error.

            //dgConnected_Users.ItemsSource = dt.DefaultView;
            dgConnected_Users.ItemsSource = dataGridUserCollection; 
            
        Cnx.Close();
    }
    catch (Exception exception)
    {
        MessageBox.Show("Erreur de chargement des données pour le motif suivant : \n" + exception.Message, "OOoopssss !!!", MessageBoxButton.OK, MessageBoxImage.Error);
    }
}

注意:-我假设列是字符串类型,然后将它们转换为字符串。在您 运行 您的代码之前,您应该处理这些最少的事情。

如果您仍然遇到任何问题,请告诉我们。