user2376998
user2376998

Reputation: 1071

WPF C# Finding controls from panel inside a panel

I have a few textboxes created dynamically , if i want to find the textboxes in the panels whats the best way to find it ?

i search online and some said through FindName we might be able to find our control but for that i need to give every of my textbox a name and in WPF , a name must come with letters not int even if i put int.ToString it will screw up . but if i put letters , it will be difficult for me to locate them by letters , numbers will be okay since i can start from 00 and +1 all the way but i can't do that .

I have textboxes dynamically created inside a dynamic created WrapPanel and i add the dynamic created WrapPanel inside a dynamic created stackPanel then i add that stackkpanel to a WrapPanel that i have created in the xaml side

if you ask me why i need so many panels because thats the only way i can make my look better because of the way i retrieve the information from db and display it .

Here is how my code looks like ( i cut it short because its too long):

       private void PopulateQuestion(int activityID, int taskID)
    {
        IList<Model.questionhint> lstQuestionHints = qh.GetRecords(taskID, activityID); 

        StackPanel sp = new StackPanel();

        foreach (Model.questionhint qhm in lstQuestionHints)

        {
            WrapPanel wp = new WrapPanel();

           //some code ....

            if (qhm.Option1.Trim().Length > 0 && 
               qhm.Option2.Trim().Length > 0)
            {
                wp.Children.Add(space);
                wp.Children.Add(tbox); //

            }
               sp.Children.Add(wp);// Adding wrap panel to stackpanel
            } // end of for each loop.

            WrapPanelTest.Children.Add(sp); // Adding stackpanel to WrapPanel ( in xaml)

        }

WrapPanelTest is the panel i created in the xaml side . So now if i have a button , how should i find the textbox controls from those panels ?

i tried :

     private void button1_Click(object sender, RoutedEventArgs e) // Check Button
    {
            int c = 0;

        foreach (TextBox txtbox in WrapPanelTest.Children)
        {
            c++;
        } 

      MessageBox.Show(c);

}

But it shows this error ( that points to TextBox txtbox in the foreach loop):

enter image description here

Upvotes: 0

Views: 4943

Answers (3)

Kamil Solecki
Kamil Solecki

Reputation: 1117

I don't get your problem with naming the controls both with letters and numbers. Do it like this:

 // This is the place where you dynamically create the textboxes, I skipped the part where u add it to wrap panel etc.
for( int numControls = 0; numControls < 30;  numControls++)
{
  Textbox box = new Texbox();
  box.name = "textbox" +     numControls.ToString();
}

And then u find it simply using

for(int numBoxes = 0;numBoxes < 30; numBoxes++)
{
Textbox box = WrapPanelTest.FindNyName("textbox" + numBoxes.ToString();
//operate on these
}

As in solution by Dick Schuerman: First, the helper class that will help us find children easier:

class ChildControls
{
    private List<object> lstChildren;

    public List<object> GetChildren(Visual p_vParent, int p_nLevel)
    {
        if (p_vParent == null)
        {
            throw new ArgumentNullException("Element {0} is null!", p_vParent.ToString());
        }

        this.lstChildren = new List<object>();

        this.GetChildControls(p_vParent, p_nLevel);

        return this.lstChildren;

    }

    private void GetChildControls(Visual p_vParent, int p_nLevel)
    {
        int nChildCount = VisualTreeHelper.GetChildrenCount(p_vParent);

        for (int i = 0; i <= nChildCount - 1; i++)
        {
            Visual v = (Visual)VisualTreeHelper.GetChild(p_vParent, i);

            lstChildren.Add((object)v);

            if (VisualTreeHelper.GetChildrenCount(v) > 0)
            {
                GetChildControls(v, p_nLevel + 1);
            }
        }
    }
}

And you use it like this:

            ChildControls ccChildren = new ChildControls();

        foreach (object o in ccChildren.GetChildren(WrapPanelTest, 5))
        {
            if (o.GetType() == typeof(TextBox))
            {
                // Do something
            }
        }

The "5" in GetChildren means how many levels deep you want to dig. Example:

  • WrapPanelTest
    • Grids
    • Textboxes

That would want you to set that property to 3.

Upvotes: 1

Dragomir Răzvan
Dragomir Răzvan

Reputation: 592

You should create a naming convention for those textboxes. For example:

int id=1;
tbox.Name="textbox_"+id.ToString();

and then create a function like:

TextBox getTextBoxById(int id)
{
   TextBox myTextBox=WrapPanelTest.FindName("textbox_"+id.ToString()) as TextBox;
   return myTextBox;
}

Upvotes: 1

Visions
Visions

Reputation: 947

In your loop you are trying to take all Controls in WrapPanelTest.Children as TextBox. try:

foreach (var control in WrapPanelTest.Children)
{
    if(control.GetType() == typeof(TextBox))
        c++;
} 

Upvotes: 3

Related Questions