Reputation: 25
I need help to finish my first little app. I'm trying to do action for checked's rows in a datagrid.
the 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>
The 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
}
}
I'm testing the code with a MessageBox for now. But nothing happen. An idea to help me to finish my project ?
In fact, I need for each row where checkbox is checked to get the UID_UserName to do a sql delete.
I have tried with DataRowView too. I can get TextColumn but nothing with checkbox.
Edit 1 :
I think a part of the problem is due that the column with checkbox is not in the 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);
}
}
Upvotes: 2
Views: 327
Reputation: 2501
I had constructed the rest of the code in order to show you the working copy.
I assume you have a class object which you are binding as an items source to data-grid. FYI, I have created my own class object. See below and change as per your class file.
Step 1 - Class creation
public class DataGridUser
{
public string UID_UserName { get; set; }
public string UID_ComputerName { get; set; }
public bool IsChecked { get; set; }
}
Step 2 - On button click, I just modified the code as below.
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);
}
}
In above code, I have used the "Cast" type and casting the item to the type that data grid is bound to which is DataGridUser (in this case).
Rest of the code is same as yours.
Edit Added code to answer your comment.
Step 3 I have copied your event handler and then made slight change. Please compare the code and read comments carefully and then use it in your program.
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);
}
}
Note:- I assume that the columns are of type string and then converting them to a string. You should take care of this minimum things before you run your code.
Let us know in case if you still face any problems.
Upvotes: 3