Динамические и неизменяемые массивы 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);
}
}
}