How to make a filter in DataGridView with two forms?

308 Views Asked by At

I have 2 Windows Forms. On the first form, I have a DataGridView and on the second form, I have just a few checkedListBoxes.

I found this question similar to my: Filtering datagridview from another form

It's looking similar to my problem, but it's not saying how I can filter information from the second form.

Also, I already asked something about this project: How can I load in Windows Forms? (C#)

It can help to understand better this situation.

enter image description here

My idea is that you have to put some marks on the second form and it's saving right now what you click, but I need to get those clicks on the first form for DGV.

The question is: How to make a filter with two forms?

Code:

 private void button2_Click_2(object sender, EventArgs e)
    {
        Form2 form2 = new Form2(this);
        form2.InitializeSecondForm();
        form2.Show();
    } 

 public void InitializeSecondForm()
    {
        this.Height = Properties.Settings.Default.SecondFormHeight;
        this.Width = Properties.Settings.Default.SecondFormWidth;
        this.Location = Properties.Settings.Default.SecondFormLocation;
        this.collectionOfTags = Properties.Settings.Default.DICOMTagSettings;

        this.FormClosing += SecondFormClosingEventHandler;
        this.StartPosition = FormStartPosition.Manual;
    } 
 private void SecondFormClosingEventHandler(object sender, FormClosingEventArgs e)
    {
        Properties.Settings.Default.SecondFormHeight = this.Height;
        Properties.Settings.Default.SecondFormWidth = this.Width;
        Properties.Settings.Default.SecondFormLocation = this.Location;
        Properties.Settings.Default.DICOMTagSettings = this.collectionOfTags;

        Properties.Settings.Default.Save();
    } 
 private void fileListDataGridView_CellContentClick(object sender, DataGridViewCellEventArgs e)
    {

        DicomFileInfo dicomFile = new DicomFileInfo();

        DataGridView datas = new DataGridView();
        
        datas.DataSource = dicomFile;

        for(int i = 0; i < datas.Rows.Count; i++)
        {
            DataGridViewLinkCell linkCell = new DataGridViewLinkCell();

            datas[2, i] = linkCell;
        }
    } 

This code for Second Form:

public partial class Form2 : Form
{
    StringCollection collectionOfTags = new StringCollection();
    public Form2()
    {
        InitializeComponent();

        InitializeSecondForm();

        LoadSettings();
    }

    
    private void LoadSettings()
    {
        for (int i = 0; i < checkedListBox1.Items.Count; i++)
        {
            var d = checkedListBox1.Items[i];
            if (collectionOfTags.Contains(d.ToString()))
            {
                int index = checkedListBox1.Items.IndexOf(d);
                if (index != -1)
                    checkedListBox1.SetItemChecked(index, true);
            }
        }

        for (int i = 0; i < checkedListBox2.Items.Count; i++)
        {
            var d = checkedListBox2.Items[i];
            if (collectionOfTags.Contains(d.ToString()))
            {
                int index = checkedListBox2.Items.IndexOf(d);
                if (index != -1)
                    checkedListBox2.SetItemChecked(index, true);
            }
        }

        for (int i = 0; i < checkedListBox3.Items.Count; i++)
        {
            var d = checkedListBox3.Items[i];
            if (collectionOfTags.Contains(d.ToString()))
            {
                int index = checkedListBox3.Items.IndexOf(d);
                if (index != -1)
                    checkedListBox3.SetItemChecked(index, true);
            }
        }

        for (int i = 0; i < checkedListBox4.Items.Count; i++)
        {
            var d = checkedListBox4.Items[i];
            if (collectionOfTags.Contains(d.ToString()))
            {
                int index = checkedListBox4.Items.IndexOf(d);
                if (index != -1)
                    checkedListBox4.SetItemChecked(index, true);
            }
        }

        for (int i = 0; i < checkedListBox5.Items.Count; i++)
        {
            var d = checkedListBox5.Items[i];
            if (collectionOfTags.Contains(d.ToString()))
            {
                int index = checkedListBox5.Items.IndexOf(d);
                if (index != -1)
                    checkedListBox5.SetItemChecked(index, true);
            }
        }

        for (int i = 0; i < checkedListBox6.Items.Count; i++)
        {
            var d = checkedListBox6.Items[i];
            if (collectionOfTags.Contains(d.ToString()))
            {
                int index = checkedListBox6.Items.IndexOf(d);
                if (index != -1)
                    checkedListBox6.SetItemChecked(index, true);
            }
        }

    }

    public void InitializeSecondForm()
    {
        this.Height = Properties.Settings.Default.SecondFormHeight;
        this.Width = Properties.Settings.Default.SecondFormWidth;
        this.Location = Properties.Settings.Default.SecondFormLocation;
        this.collectionOfTags = Properties.Settings.Default.DICOMTagSettings;

        this.FormClosing += SecondFormClosingEventHandler;
        this.StartPosition = FormStartPosition.Manual;
    }

    private void SecondFormClosingEventHandler(object sender, FormClosingEventArgs e)
    {
        Properties.Settings.Default.SecondFormHeight = this.Height;
        Properties.Settings.Default.SecondFormWidth = this.Width;
        Properties.Settings.Default.SecondFormLocation = this.Location;
        Properties.Settings.Default.DICOMTagSettings = this.collectionOfTags;

        Properties.Settings.Default.Save();
    }

    private void button1_Click(object sender, EventArgs e)
    {
       
        Properties.Settings.Default.DICOMTagSettings.Clear();

        Properties.Settings.Default.DICOMTagSettings
.AddRange(checkedListBox1.CheckedItems.Cast<string>().ToArray());
        foreach (string s in Properties.Settings.Default.DICOMTagSettings)
        {
            int index = checkedListBox1.Items.IndexOf(s);
            if (index != -1) checkedListBox1.SetItemChecked(index, true);

            for (int i = 0; i < checkedListBox1.Items.Count; i++)
            {
            }

        }

        Properties.Settings.Default.DICOMTagSettings
.AddRange(checkedListBox2.CheckedItems.Cast<string>().ToArray());
        foreach (string t in Properties.Settings.Default.DICOMTagSettings)
        {
            int index = checkedListBox2.Items.IndexOf(t);
            if (index != -1) checkedListBox2.SetItemChecked(index, true);
        }

        Properties.Settings.Default.DICOMTagSettings
.AddRange(checkedListBox3.CheckedItems.Cast<string>().ToArray());
        foreach (string c in Properties.Settings.Default.DICOMTagSettings)
        {
            int index = checkedListBox3.Items.IndexOf(c);
            if (index != -1) checkedListBox3.SetItemChecked(index, true);
        }

        Properties.Settings.Default.DICOMTagSettings
.AddRange(checkedListBox4.CheckedItems.Cast<string>().ToArray());
        foreach (string a in Properties.Settings.Default.DICOMTagSettings)
        {
            int index = checkedListBox4.Items.IndexOf(a);
            if (index != -1) checkedListBox4.SetItemChecked(index, true);
        }

        Properties.Settings.Default.DICOMTagSettings
.AddRange(checkedListBox5.CheckedItems.Cast<string>().ToArray());
        foreach (string k in Properties.Settings.Default.DICOMTagSettings)
        {
            int index = checkedListBox5.Items.IndexOf(k);
            if (index != -1) checkedListBox5.SetItemChecked(index, true);
        }

        Properties.Settings.Default.DICOMTagSettings
 .AddRange(checkedListBox6.CheckedItems.Cast<string>().ToArray());
        foreach (string q in Properties.Settings.Default.DICOMTagSettings)
        {
            int index = checkedListBox6.Items.IndexOf(q);
            if (index != -1) checkedListBox6.SetItemChecked(index, true);
        }
        this.Close();
    }
2

There are 2 best solutions below

0
Florian Schmidinger On

What you need is a way to send data from one object to another. There are many possibilities but the most cleanest ones are either implementing the Observer Pattern or make use of events which is the simplest form to implement the Observer Pattern.

Much like you subscribe to a Buttons clickevent from the form, you can also expose events yourself and with the corresponding eventargs send data to whatever is subscribed to your events:

public class Form1 // ignore class names it's just to demonstrate =)
{
    // ... other code

    public void PickTags_Click(object sender, EventArgs args)
    {
        // i suppose you instanciate the form here...
    
        var filterForm = new FormWithFilters();
    
        filterForm.FilterChanged += OnFilterChanged; // here you subscribe
        filterForm.Show();
     }

    public void OnFilterChanged(object sender, FilterEventArgs args)
    {
        // ... apply your filter
    }
}

public class FormWithFilters
{
    // ... other code
    
    public void YourUiHandler(object sender, EventArgs args)
    {
        // collect the data for the filter
        
        var eventArgs = new FilterEventArgs
        {
            // assign your Properties for the subscribers to consume
        };
        
        FilterChanged?.Invoke(this, eventArgs); // notify subscribers
    }
    
    
    public event EventHandler<FilterEventArgs> FilterChanged; // your very own event
}

public class FilterEventArgs : EventArgs
{
    // add whatever properties you need to communicate what has to be filtered...
}
12
JohnG On

It is not clear “when” you want to update the grid in form 1. With over 40 options for the user to choose from, then I would think that you would update the grid when the user clicks the OK button on form 2. In that situation, you could use a ShowDialog for form 2 and after form 2 is closed, your code should still be able to grab any “public” variables in form 2. So if you make the CheckListBox(s) in form 2 “public” then you can examine them in form 1 like below.

private void buttonToOpenForm2_Click(object sender, EventArgs e) {
  Form2 f2 = new Form2();
  f2.ShowDialog();
  StringBuilder sb = new StringBuilder();
  sb.AppendLine("Checked Options are: ... ");
  for (int i = 0; i < f2.checkedListBox1.Items.Count; i++) {
    sb.AppendLine("Option: " + f2.checkedListBox1.Items[i].ToString());
    sb.AppendLine("          " + (f2.checkedListBox1.GetItemChecked(i) ? " Is" : "Is Not") + " Checked");
  }
  textBox1.Text = sb.ToString();
}

enter image description here

Obviously if form 2 does NOT expose the CheckedListBoxes as public, then you will not be able to see them in form 1. In the designer for form 2… select the CheckListBox(s) and change the Modifier property to true.

Edit...

Try the pseudo code below which is incomplete. I made a “global” List<string> collectionOfTagsMaster that keeps a list of all the tags. When the second from is closed, the code creates a new list of all tags, then loops though the CheckedListBox box on form2. If the tag is NOT checked then we remove that tag from curTags list of tags. If the tag IS checked then we leave the tag in the list.

After that a simple loop through all the columns in the grid to set it visible or invisible depending on if its column name is contained in the curTags collection. In my small tests, using a grid with a data table data source worked as expected.

List<string> collectionOfTagsMaster = new List<string>();
// fill list with all tags

private void buttonToOpenForm2_Click(object sender, EventArgs e) {
  Form2 f2 = new Form2();
  f2.ShowDialog();
  List<string> curTags = new List<string>(collectionOfTagsMaster);
  for (int i = 0; i < f2.checkedListBox1.Items.Count; i++) {
    if (!f2.checkedListBox1.GetItemChecked(i)) {
      curTags.Remove(f2.checkedListBox1.Items[i].ToString());
    }
  }
  foreach (DataGridViewColumn column in dataGridView1.Columns) {
    if (curTags.Contains(column.Name)) {
      column.Visible = true;
    }
    else {
      column.Visible = false;
    }
  }
}

Lastly, can you explain the code in the fileListDataGridView_CellContentClick event. It looks odd and appears to accomplish nothing. Can you explain what the code is supposed to be doing?