Click here to Skip to main content
15,888,351 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
Hey guys I am now trying generate button in WPF but I have problem
foreach (var b in control)
{
   this.GenerateFGridPanel.Children.Add(b);
}

In stackflow I find I must use it "Childen" for WPF instead of Control which I use it in Winforms. I hope so its ok... ahhh
Using this I get problem error "Exception Unhandled" - System.ArgumentException: 'Specified Visual is already a child of another Visual or the root of a CompositionTarget.'

Thanks for advice how dynamically generate in WPF. In Winforms I generete to flowlayoutpanel but this its not so I thinkng trying generete to grid but I have little problem with generating :( and I am little confused how solve this.

What I have tried:

My Code MainWindows.xaml.cs
public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
        #region variables
        private int counter = 1;
        string value = string.Empty;
        private btnMini btnM = new btnMini();
        private List<Control> control = new List<Control>();
        #endregion

        private void myButton_Click(object sender, RoutedEventArgs e)
        {
            for (int i = 0; i < Int32.Parse(value); i++)
            {
                btnM = new btnMini();
                btnM.Name = "btn_" + counter;
                btnM.ButtonClick += (sender, e) => btnTestClick(this, e);
                counter++;
                control.Add(btnM);
                foreach (var b in control)
                {
                    this.GenerateFGridPanel.Children.Add(b);
                }
            }
        }

        private void mySlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
                if (value != null)
                    value = mySlider.Value.ToString();
        }
        
        private void btnTestClick(object sender, EventArgs e)
        {
            var temp = sender as Button;
            //MessageBox.Show("Parent name of control - btnMini " + temp.Parent.Parent.Name + ", button name is " + temp.Name);
        }

XAml mainwindows
<Window x:Name="Form" x:Class="WpfApp4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp4"
        mc:Ignorable="d"
        Title="TestApp" Height="500" Width="592" ResizeMode="NoResize" WindowStyle="SingleBorderWindow" HorizontalAlignment="Left" VerticalAlignment="Center">
    <Grid>
        <Slider x:Name="mySlider"
                Maximum="30" TickPlacement="BottomRight" TickFrequency="1"
                IsSnapToTickEnabled="True" Minimum="1"
                Value="1" ValueChanged="mySlider_ValueChanged" Margin="0,0,0,449">
        </Slider>
        <Grid x:Name="GenerateFGridPanel" Margin="0,122,0,0" Background="#FFB8B8B8">
            
        </Grid>
        <Button x:Name="myButton" Content="Generate buttons" Click="myButton_Click" Margin="10,75,466,0" Height="33" VerticalAlignment="Top"></Button>
        <TextBox x:Name="textBox" HorizontalAlignment="Left" Margin="10,44,0,0" Text="TextBox" TextWrapping="Wrap" VerticalAlignment="Top" Width="134" Height="26"/>
        <Label x:Name="lblText" Content="Label" HorizontalAlignment="Left" Margin="163,44,0,0" VerticalAlignment="Top" RenderTransformOrigin="0.263,-0.345"/>
    </Grid>
</Window>
Posted
Updated 10-Aug-21 22:12pm
v3

1 solution

Quote:
C#
for (int i = 0; i < Int32.Parse(value); i++)
{
    btnM = new btnMini();
    btnM.Name = "btn_" + counter;
    btnM.ButtonClick += (sender, e) => btnTestClick(this, e);
    counter++;
    control.Add(btnM);
    foreach (var b in control)
    {
        this.GenerateFGridPanel.Children.Add(b);
    }
}
Step through your code and see what it is doing in the debugger. Your logic is not correct.

On the first run through the loop, you create a button, add it to a List<Control>, and then add it as a child of the GenerateFGridPanel.

On the second run through the loop, you create another button and add it to the List<Control>. You then try to add both buttons as children of the GenerateFGridPanel control.

Since the first button has already been added as a child, you cannot add it again.

Either drop the list and add the controls as you create them, or move the foreach loop out of the for loop.
C#
for (int i = 0; i < Int32.Parse(value); i++)
{
    btnM = new btnMini();
    btnM.Name = "btn_" + counter;
    btnM.ButtonClick += (sender, e) => btnTestClick(this, e);
    counter++;
    this.GenerateFGridPanel.Children.Add(btnM);
}
Or:
C#
for (int i = 0; i < Int32.Parse(value); i++)
{
    btnM = new btnMini();
    btnM.Name = "btn_" + counter;
    btnM.ButtonClick += (sender, e) => btnTestClick(this, e);
    counter++;
    control.Add(btnM);
}

foreach (var b in control)
{
    this.GenerateFGridPanel.Children.Add(b);
}
 
Share this answer
 
Comments
Beji_ 11-Aug-21 5:04am    
Thank you, I'm totally stupid. I didn't notice that I have a foreach in the loop for. I played with it last night and when it bore it I said to myself what I was doing to you and I didn't notice this. Thanks for the help and I apologize for the unnecessary question that I would have noticed myself for sure if I had looked at it better that evening. So thanks :)

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900