Динамические и неизменяемые массивы UIElement

У меня есть WrapPanel который содержит несколько Canvas того же размера. каждый Canvas имеет некоторые UIElementс (то есть TextBox, TextBlock, Buttonи т. д.) как дети. Создание каждого Canvas (включая его UIElement дети) и количество Canvas Все, что должно быть создано, выполняется в коде времени выполнения (без XAML).

Изначально я сделал следующее, что работает:

// declare as class properties, so all function can access them
WrapPanel wp = new WrapPanel();
Canvas[] cv = new Canvas[500];
TextBox[] tb = new TextBox[500];

// A function (e.g. a Button_Click event) that generates multiple Canvas in a WrapPanel
for (int i = 0; i<myInt; i++)
{
cv[i] = new Canvas();
tb[i] = new TextBox();
cv[i].Children.Add(tb[i]);
wp.Children.Add(cv[i]);
}

Вышеприведенный код работает нормально. До тех пор, пока я не реализую кнопки добавления, минуса и уничтожения, где я мог

1. Add an additional `Canvas` on a click event
2. Remove the last `Canvas` on a click event
3. Destroy a specific `Canvas` in the `WrapPanel` on a click event (may ba a little cross icon in each `Canvas`)

Если я обработаю некоторую комбинацию из трех вышеупомянутых действий, я мог бы легко создать элементы UIE с тем же индексом или создать Canvas, выходящий за пределы того, что было объявлено изначально.

Однако я посмотрел на List, каждый Canvas имеет разные свойства (у каждого также есть UIElement Children с разными свойствами), и я не могу понять, как List решит это. Для меня способ обойти это - объявить очень большой размер массива для Canvas (например, Canvas[] cv = new Canvas[99999], но я думаю, что это не очень эффективно).

Кроме того, если я использую List, как я могу изменить свойства определенного UIElement после того, как они сгенерированы? Например, если я добавлю 10 Canvas и добавлю в список, и после того, как они все сгенерированы, мне нужно выбрать 5-й холст и изменить TextBox.Text, как мне получить к нему доступ, как я это сделал в массиве (то есть tb[5]).Text = "Hello")?

Может кто-нибудь показать мне некоторые подходы к этой проблеме?

2 ответа

Решение

Просто прямой перевод о том, как сделать это с помощью списка ниже. Учитывая ваш код, я не знаю, почему вы хотите отслеживать холст и текстовые поля в списке - вы можете просто получить доступ к коллекции детей WrapPanel Вместо этого, давайте предположим, что вам сейчас нужны эти отдельные коллекции.

 WrapPanel wp = new WrapPanel();
 List<Canvas> cvList = new List<Canvas>();
 List<TextBox> tbList = new List<TextBox>();

 public void Init()
{

    int myInt = 500;
    // in a function (e.g. a Button_Click event) to generate the multiple Canvas in a WrapPanel
    for (int i = 0; i < myInt; i++)
    {
        Canvas cv = new Canvas();
        TextBox tb = new TextBox();
        cv.Children.Add(tb);
        wp.Children.Add(cv);

        cvList.Add(cv);
        tbList.Add(tb);
    }
}


public void AddCanvas()
{
    Canvas cv = new Canvas();
    TextBox tb = new TextBox();
    cv.Children.Add(tb);
    wp.Children.Add(cv);
    cvList.Add(cv);
    tbList.Add(tb);
}

public void RemoveCanvas()
{
        wp.Children.RemoveAt(wp.Children.Count-1);
        cvList.RemoveAt(cvList.Count - 1);
        tbList.RemoveAt(cvList.Count - 1);
}

Изменить для добавления комментария:

Например, если я добавлю 10 Canvas, и после того, как все они будут сгенерированы, мне нужно выбрать 5-й холст и изменить TextBox.Text, как мне получить к нему доступ, как в массиве (т.е. tb[5].Text = "Hello")?

Вы можете просто получить доступ к детям напрямую. Вы знаете, что вы только добавили Canvas элементы к вашему WrapPanel, Так что вы могли бы сделать (wp является WrapPanel снова):

TextBox textbox = (wp.Children[5] as Canvas).Children[0] as TextBox;
textbox.Text = "Hello";

Просто работайте прямо на WrapPanelДетская коллекция.

public partial class MainWindow : Window
{        

    public MainWindow()
    {
        InitializeComponent();
        AddCanvasToWrapPanel(this.TestWrapPanel);
        RemoveLastCanvasFromWrapPanel(this.TestWrapPanel);
        AddCanvasToWrapPanel(this.TestWrapPanel);
        DestroyCanvasAtWrapPanelIndex(this.TestWrapPanel, 0);

    }

    private void AddCanvasToWrapPanel(WrapPanel wp)
    {
        TextBox t = new TextBox();
        Canvas c = new Canvas();
        c.Children.Add(t);
        wp.Children.Add(c);
    }

    private void RemoveLastCanvasFromWrapPanel(WrapPanel wp)
    {
        wp.Children.RemoveAt(wp.Children.Count - 1);
    }

    private void DestroyCanvasAtWrapPanelIndex(WrapPanel wp, int index)
    {
        wp.Children.RemoveAt(index);
    }


}
}
Другие вопросы по тегам