Dim
Dim

Reputation: 4807

WPF dynamically created buttons and expanders control

I am creating dynamically buttons with expander below each button. When each button clicked I want that the expander below this button will open. How can I know in each button click which expander to open?

public partial class MainWindow : Window
{

    List<List<string>> Buttons;


    public MainWindow()
    {
        InitializeComponent();

        Buttons = new List<List<string>>();

        /////////////////////////////////////////
        List<string> lst1 = new List<string>();
        lst1.Add("main1");
        lst1.Add("a1");
        lst1.Add("a2");
        lst1.Add("a3");
        lst1.Add("a4");
        Buttons.Add(lst1);
        /////////////////////////////////////////
        List<string> lst2 = new List<string>();
        lst2.Add("main2");
        lst2.Add("b1");
        lst2.Add("b2");
        lst2.Add("b3");
        lst2.Add("b4");
        Buttons.Add(lst2);
        /////////////////////////////////////////
        List<string> lst3 = new List<string>();
        lst3.Add("main3");
        lst3.Add("c1");
        lst3.Add("c2");
        lst3.Add("c3");
        lst3.Add("c4");
        Buttons.Add(lst3);

        for (int i = 0; i < Buttons.Count; i++)
        {
            Button newBtn = new Button();
            newBtn.Content = Buttons[i][0];
            newBtn.Name = "Button" + i.ToString();

            newBtn.Height = 23;
            stackPanel1.Children.Add(newBtn);
            newBtn.Click += new RoutedEventHandler(newBtn_Click);


            Expander expader = new Expander();
            StackPanel newStck = new StackPanel();

            for (int j = 1; j < Buttons[i].Count; j++)
            {
                Button newBtnIn = new Button();
                newBtnIn.Content = Buttons[i][j];
                newBtnIn.Name = "Button" + j.ToString();
                newBtnIn.Height = 23;
                newBtnIn.Width = 100;

                newStck.Children.Add(newBtnIn);
            }

            expader.Content = newStck;
            stackPanel1.Children.Add(expader);
        }


    }

    private void newBtn_Click(object sender, RoutedEventArgs e)
    {
         //open specific expander below button
    }
}

Upvotes: 0

Views: 1216

Answers (2)

Anatolii Gabuza
Anatolii Gabuza

Reputation: 6260

I suppose you should use ToggleButton instead of Button this allows you to handle IsChecked state and as a result expand/collapse underlying Expander control.
As a result you'll be able to define DataTemplate with ToggleButton and Expander within:

<DataTemplate>
   <StackPanel>
     <ToggleButton x:Name="expandButton" IsChecked="false"/>
     <Expander IsExpanded="{Binding IsChecked, ElementName=expandButton}">
        <TextBlock TextWrapping="Wrap">
             Lorem ipsum dolor sit amet, consectetur
             adipisicing elit, sed do eiusmod tempor incididunt ut
             labore et dolore magna aliqua
        </TextBlock>
     </Expander>
   </StackPanel>
</DataTemplate>

Afterwards you should consider using either ListView, ListBox or any other suitable control with ItemsSource set to be your buttons list. This will give you clean design without a lot of code-behind, which is not so good as practice shows.

Upvotes: 0

user1064248
user1064248

Reputation:

You may give the button a reference to it's expander useing the Tag property of the button. A working solution would be:

 public partial class MainWindow : Window
{

    List<List<string>> Buttons;


    public MainWindow()
    {
        InitializeComponent();

        Buttons = new List<List<string>>();

        /////////////////////////////////////////
        List<string> lst1 = new List<string>();
        lst1.Add("main1");
        lst1.Add("a1");
        lst1.Add("a2");
        lst1.Add("a3");
        lst1.Add("a4");
        Buttons.Add(lst1);
        /////////////////////////////////////////
        List<string> lst2 = new List<string>();
        lst2.Add("main2");
        lst2.Add("b1");
        lst2.Add("b2");
        lst2.Add("b3");
        lst2.Add("b4");
        Buttons.Add(lst2);
        /////////////////////////////////////////
        List<string> lst3 = new List<string>();
        lst3.Add("main3");
        lst3.Add("c1");
        lst3.Add("c2");
        lst3.Add("c3");
        lst3.Add("c4");
        Buttons.Add(lst3);

        for (int i = 0; i < Buttons.Count; i++)
        {
            Button newBtn = new Button();
            newBtn.Content = Buttons[i][0];
            newBtn.Name = "Button" + i.ToString();

            newBtn.Height = 23;
            stackPanel1.Children.Add(newBtn);
            newBtn.Click += new RoutedEventHandler(newBtn_Click);


            Expander expader = new Expander();
            StackPanel newStck = new StackPanel();

            for (int j = 1; j < Buttons[i].Count; j++)
            {
                Button newBtnIn = new Button();
                newBtnIn.Content = Buttons[i][j];
                newBtnIn.Name = "Button" + j.ToString();
                newBtnIn.Height = 23;
                newBtnIn.Width = 100;
                newBtn.Tag = expader;
                newBtn.Click+=newBtn_Click;
                newStck.Children.Add(newBtnIn);
            }

            expader.Content = newStck;
            stackPanel1.Children.Add(expader);
        }


    }

    private void newBtn_Click(object sender, RoutedEventArgs e)
    {
        Button b = sender as Button;

        if (b == null)
            return;

        Expander ex = b.Tag as Expander;

        if (ex == null)
            return;

        ex.IsExpanded = !ex.IsExpanded;
    }
}

Upvotes: 1

Related Questions