2

I have created a program that needs to show 5 data grids at the bottom of my WPF application however the program will only show one at a time. Or it will show 3 boxes but only one Datagrid will contain any data.

This is the code I have so far:

private void SearchButton_Click(object sender, RoutedEventArgs e)
    {

        if (GPBox.IsChecked == true)
        {
            connect = new MySqlConnection(connectionString);
            cmd = new MySqlCommand("select distinct nameOfService as Surgeries, street, city, postcode, contactNumber from gpSurgery", connect);
            connect.Open();
            DataTable dt = new DataTable();
            dt.Load(cmd.ExecuteReader());
            connect.Close();
            DataGridGP.Visibility = Visibility.Visible;
            DataGridGP.DataContext = dt;
        }  

        else if (DentistBox.IsChecked == true)
        {
            connect = new MySqlConnection(connectionString);
            cmd = new MySqlCommand("select distinct nameOfService as Dentists, street, city, postcode, contactNumber from Dentist", connect);
            connect.Open();
            DataTable dt = new DataTable();
            dt.Load(cmd.ExecuteReader());
            connect.Close();
            DataGridDentist.Visibility = Visibility.Visible;
            DataGridDentist.DataContext = dt;

        }
        else if (SchoolsBox.IsChecked == true)
        {
            connect = new MySqlConnection(connectionString);
            cmd = new MySqlCommand("select distinct nameOfService as Schools, street, city, postcode, contactNumber from Schools", connect);
            connect.Open();
            DataTable dt = new DataTable();
            dt.Load(cmd.ExecuteReader());
            connect.Close();
            DataGridSchools.Visibility = Visibility.Visible;
            DataGridSchools.DataContext = dt;

        }
        else if (NurseryBox.IsChecked == true)
        {
            connect = new MySqlConnection(connectionString);
            cmd = new MySqlCommand("select distinct nameOfService as Nurserys, street, city, postcode, contactNumber from Nursery", connect);
            MySqlDataAdapter sqlDA = new MySqlDataAdapter();
            DataTable dt = new DataTable();
            dt.Load(cmd.ExecuteReader());
            connect.Close();
            DataGridNursery.Visibility = Visibility.Visible;
            DataGridNursery.DataContext = dt;
        }

        else if (OpticianBox.IsChecked == true)
        {
            connect = new MySqlConnection(connectionString);
            cmd = new MySqlCommand("select distinct nameOfService as Opticians, street, city, postcode, contactNumber from Opticians", connect);
            MySqlDataAdapter sqlDA = new MySqlDataAdapter();
            DataTable dt = new DataTable();
            dt.Load(cmd.ExecuteReader());
            connect.Close();
            DataGridOpticians.Visibility = Visibility.Visible;
            DataGridOpticians.DataContext = dt;
        }
        else
        {
            MessageBox.Show("Select a service.");
        }

    }

XAML code:

<DataGrid Name="DataGridGP" Height="57" VerticalAlignment="Top" Margin="0,129,10,0" ItemsSource="{Binding}" Visibility="Collapsed"  />
    <DataGrid Name="DataGridDentist" HorizontalAlignment="Left" Height="57" Margin="0,191,0,0" VerticalAlignment="Top" Width="782" Visibility="Collapsed"/>
    <DataGrid Name="DataGridSchools" HorizontalAlignment="Left" Height="57" Margin="0,253,0,0" VerticalAlignment="Top" Width="782" Visibility="Collapsed"/>
    <DataGrid Name="DataGridNursery" Height="57" Margin="0,315,10,0" VerticalAlignment="Top" Visibility="Collapsed"/>
    <DataGrid Name="DataGridOpticians" HorizontalAlignment="Left" Height="57" Margin="0,377,0,0" VerticalAlignment="Top" Width="782" Visibility="Collapsed"/>

Can anyone see why it shows only one Datagrid or none at all?

Thanks

2 Answers2

0

The problem seems to be in your c# code. You're using else if in each of your conditions, which means the code in that block will only run if none of the previous conditions were met. For example:

void test()
{
    int i = 5;

    if (i < 2)
    {
        System.Diagnostics.Debug.Print("< 2");
    }
    else if (i > 2)
    {
        System.Diagnostics.Debug.Print("> 2");
    }
    else if(i == 5)
    {
        System.Diagnostics.Debug.Print("= 5");
    }
}

In the above, i < 2 will evaluate to false.
i > 2 will evaluate to true and the Print code will run.
But i == 5 will never be checked, because we already found our match.

In your code, if you want the user to be able to check off mutliple boxes and have each of those DataGrids load, then you'll want to replace the else ifs with normal ifs.

Note on Code Redundancy

In general, you should avoid having many different versions of very similar code, like you have in yours. In each of those if blocks, the code you're running is almost the same. If you ever needed to change it, you would have to change it 5 times.

Instead, you should use a method and pass it the needed variables, like so:

void loadDataGrid(string command, DataGrid dataGrid)
{
    connect = new MySqlConnection(connectionString);
    cmd = new MySqlCommand(command, connect);
    MySqlDataAdapter sqlDA = new MySqlDataAdapter();
    DataTable dt = new DataTable();
    dt.Load(cmd.ExecuteReader());
    connect.Close();
    dataGrid.Visibility = Visibility.Visible;
    dataGrid.DataContext = dt;
}

Your SearchButton_Click then becomes:

private void SearchButton_Click(object sender, RoutedEventArgs e)
{

    if (GPBox.IsChecked == true)
    {
        loadDataGrid("select distinct nameOfService as Surgeries, street, city, postcode, contactNumber from gpSurgery", DataGridGP)
    }

    ...
}

Each if condition now has only one line of code instead of eight.

Note on WPF Layout

Generally speaking, you shouldn't be using fixed Margin values to position WPF elements relative to each other. This begins to defeat the purpose of WPF's layout system, which lets you build very flexible designs. Instead, you would use one of the various types of Panel.

For your case, I might recomend a 'StackPanel, since you want to stack yourDataGrid`s vertically on top of each other.

Keith Stein
  • 6,235
  • 4
  • 17
  • 36
0

Agreed with other answer about code redundancy, but also you can probably significantly simplify with a SINGLE grid and a SINGLE DataTable. Make a public DataTable available as your binding source...

public DataTable YourData {get; private set;}

Then in your xaml, you can set the

<DataGrid ItemsSource="{Binding YourData}" ... >

When you are querying, you would just need to change the first column in the datagrid to the "nameOfService" column since each query is returning the same column name so the data grid always uses the same table columns... such as

   string defTable = "";
   if( GPBox.IsChecked )
      defTable = "gpSurgery";
   else if (DentistBox.IsChecked == true)
      defTable = "Dentist";
   else if (SchoolsBox.IsChecked == true)
      defTable = "Schools";
   else if (NurseryBox.IsChecked == true)
      defTable = "Nursery";
   else if (OpticianBox.IsChecked == true)
      defTable = "Opticians";
   else
   {
      MessageBox.Show("Select a service.");
      return;
   }

   // valid choice...
   // this is NOT going to be an issue of SQL-Injection because YOU are 
   // controlling the string values for the table name to query from.
   connect = new MySqlConnection(connectionString);
   cmd = new MySqlCommand("select distinct nameOfService, street, city, postcode, contactNumber from " + defTable, connect);
   MySqlDataAdapter sqlDA = new MySqlDataAdapter();
   YourData = new DataTable();
   YourData.Load(cmd.ExecuteReader());
   connect.Close();

This could significantly help on code maintenance. This way, you could have a single grid, not worry about collapsing and/or visibility of which one to show. It also appears you are not explicitly declaring the columns to show, so that they are probably auto-creating the columns when binding is updated.

DRapp
  • 47,638
  • 12
  • 72
  • 142
  • This would be good if they only want to show a single `DataGrid` at a time, but I think their problem is that they want to show a dynamic number of `DataGrid`s based on user selection. – Keith Stein Dec 04 '19 at 16:49
  • @KeithStein, I disagree and you could be correct, but their opening statement says only one will be visible at a time... Just showing an alternative to their design. – DRapp Dec 04 '19 at 16:51