2014-10-12 3 views
-6

Мне нужен способ динамического создания нескольких текстовых полей и доступа к их значениям.Dynamically Generated TextBoxes

В моей форме пользователь вводит число в диапазоне от 1 до 50, а затем, что количество текстовых полей должны быть созданы с динамическими именами т.е. ingredient1, ingredient2, ingredient3, ... ingredient50 т.д.

У меня есть для цикл, который будет создавать несколько текстовых полей с использованием значения, но как сохранить значение текстового поля в строковой переменной?

Здесь цикл в настоящее время пустой

int i = Form1.ingredientCount; 

for (i = 1; i < Form1.ingredientCount; i++) 
{ 
    //create new text box 
    //create new string that then holds value from text box 
} 

Для пояснения:

пользователь вводит номер на предыдущей странице.

Затем этот номер определяет количество созданных текстовых полей и количество созданных строк.

Текстовые поля и строки должны иметь уникально сгенерированные идентификаторы в цикле for.

Мне также нужно другое текстовое поле для веса каждого ингредиента, хотя я мог бы понять это сам.

Поэтому в основном я хочу каждый текстовое поле и строка будет называться что-то вроде

"input" + i (где я есть инкрементора) так, что бы имя будет «input1», «input2», «вход3» и так на.

То же самое со строкой, которая будет содержать данные из текстового поля.

+0

Если ингредиенты должны быть чем-то вроде «дрожжей», «яиц», «сахара» ... просто выщипывать их из массива – Plutonix

+0

Я не уверен, что вы спрашиваете здесь.Я смущен тем, где находится текстовое поле, и что вы подразумеваете под тем, чтобы они были в глобальных переменных. В C# есть несколько вещей, которые можно было бы рассматривать как «глобальные переменные», но не понятие, которое на самом деле называется «глобальной переменной», поэтому было бы полезно узнать, чего вы пытаетесь выполнить. –

+0

Привет, я попытаюсь объяснить более подробно Прежде всего пользователь вводит число . Затем этот номер используется в цикле for . Затем цикл for должен генерировать новое текстовое поле и уникальное имя строки для хранения что пользователь вводит в каждое из этих текстовых полей. Таким образом, строка в основном чтение текстового поля т.е. string1 = TextBox1.ToString() строка2 = TextBox2.ToString() ... string50 = TextBox50.ToString() –

ответ

0

Я думал, я бы изменить его, как это кажется, я неправильно понял вопрос

вы могли бы связать его в том виде, как следующее:

public partial class Form1 : Form 
{ 
    Recepie pancakes = new Recepie(); 
    IList<UniqueHolder> items = new List<UniqueHolder>(); 

    public Form1() 
    { 
     InitializeComponent(); 
     pancakes.Ingredients.Add(new Ingredient { Title = "Milk - 250 gr" }); 
     pancakes.Ingredients.Add(new Ingredient { Title = "Butter - 25 gr" }); 
     pancakes.Ingredients.Add(new Ingredient { Title = "Oil - 1 large spoon" }); 
     pancakes.Ingredients.Add(new Ingredient { Title = "Sugar - 100 gr" }); 
     pancakes.Ingredients.Add(new Ingredient { Title = "Flower - 200 gr" }); 
    } 

    private void Form1_Load(object sender, EventArgs e) 
    { 

    } 

    private void button1_Click(object sender, EventArgs e) 
    { 
     for (var i = 0; i < pancakes.Ingredients.Count; i++) 
     { 
      Ingredient ing = pancakes.Ingredients[i]; 
      TextBox tb = new TextBox { Location = new Point(10, i * 30), Size = new Size(200, 20), Text = ing.Title }; 
      UniqueHolder uh = new UniqueHolder { Ingredient = ing, TextBox = tb }; 
      this.Controls.Add(tb); 
     } 
    } 
} 

Уникальный держатель делает привязки данных об изменениях в либо ингредиент или текстовое поле

public class UniqueHolder : IDisposable 
{ 
    public Guid UniqueID { get; set; } 

    public override bool Equals(object obj) 
    { 
     if (obj is UniqueHolder) 
     { 

      return Guid.Equals(((UniqueHolder)obj).UniqueID, this.UniqueID); 
     } 
     return base.Equals(obj); 
    } 

    public override int GetHashCode() 
    { 
     return UniqueID.GetHashCode(); 
    } 

    private TextBox textbox; 
    public TextBox TextBox 
    { 
     get 
     { 
      return textbox; 
     } 
     set 
     { 
      if (object.Equals(textbox, value)) 
      { 
       return; 
      } 
      if (textbox != null) 
      { 
       textbox.TextChanged -= OnTextChanged; 
      } 
      textbox = value; 
      if (textbox != null) 
      { 
       textbox.TextChanged += OnTextChanged; 
      } 
     } 
    } 

    private Ingredient ingredient; 
    public Ingredient Ingredient 
    { 
     get 
     { 
      return ingredient; 
     } 
     set 
     { 
      if (object.Equals(ingredient, value)) 
      { 
       return; 
      } 
      if (ingredient != null) 
      { 
       ingredient.PropertyChanged -= OnIngredientChanged; 
      } 
      ingredient = value; 
      if (ingredient != null) 
      { 
       ingredient.PropertyChanged += OnIngredientChanged; 
      } 
     } 
    } 

    public UniqueHolder() 
    { 
     this.UniqueID = Guid.NewGuid(); 
    } 

    protected virtual void OnIngredientChanged(object sender, PropertyChangedEventArgs e) 
    { 
     if (string.Equals(e.PropertyName, "Title", StringComparison.OrdinalIgnoreCase)) 
     { 
      if (TextBox == null) 
      { 
       return; 
      } 
      TextBox.Text = Ingredient.Title; 
     } 
    } 

    protected virtual void OnTextChanged(object sender, EventArgs e) 
    { 
     var tb = sender as TextBox; 
     if (tb == null) 
     { 
      return; 
     } 
     if (Ingredient == null) 
     { 
      return; 
     } 
     Ingredient.Title = tb.Text; 
    } 

    public void Dispose() 
    { 
     Ingredient = null; 
     TextBox = null; 
    } 
} 

И вы можете вернуться к recepie с использованием ингредиентов, таких

public class Recepie : IDisposable 
{ 
    private readonly IList<Ingredient> ingredients = new ObservableCollection<Ingredient>(); 
    public IList<Ingredient> Ingredients 
    { 
     get 
     { 
      return ingredients; 
     } 
    } 

    protected virtual void OnIngredientsListChanged(object sender, NotifyCollectionChangedEventArgs e) 
    { 
     if (e.OldItems != null) 
     { 
      foreach (var item in e.OldItems) 
      { 
       var ing = item as Ingredient; 
       if (ing == null) 
       { 
        continue; 
       } 
       ing.Recepie = null; 
      } 
     } 
     if (e.NewItems != null) 
     { 
      foreach (var item in e.NewItems) 
      { 
       var ing = item as Ingredient; 
       if (ing == null) 
       { 
        continue; 
       } 
       ing.Recepie = this; 
      } 
     } 
    } 

    public Recepie() 
    { 
     var obs = Ingredients as INotifyCollectionChanged; 
     if (obs != null) 
     { 
      obs.CollectionChanged += OnIngredientsListChanged; 
     } 
    } 

    public void Dispose() 
    { 
     int total = Ingredients.Count; 
     for (int i = total; --i >= 0;) 
     { 
      Ingredients.RemoveAt(i); 
     } 
     var obs = Ingredients as INotifyCollectionChanged; 
     if (obs != null) 
     { 
      obs.CollectionChanged -= OnIngredientsListChanged; 
     } 
    } 
} 

public class Ingredient : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 

    private Recepie recepie; 
    public virtual Recepie Recepie 
    { 
     get 
     { 
      return recepie; 
     } 
     set 
     { 
      if (object.Equals(recepie, value)) 
      { 
       return; 
      } 
      recepie = value; 
      RaisePropertyChanged("Recepie"); 
     } 
    } 

    private string title; 
    public string Title 
    { 
     get 
     { 
      return title; 
     } 
     set 
     { 
      if (string.Equals(title, value)) 
      { 
       return; 
      } 
      title = value; 
      RaisePropertyChanged("Title"); 
     } 
    } 

    protected virtual void RaisePropertyChanged(string propertyName) 
    { 
     var local = PropertyChanged; 
     if (local != null) 
     { 
      local.Invoke(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
} 
+0

guid создает случайные строки справа? Мне нужно иметь возможность манипулировать и получать доступ к этим строкам позже в программе. Извините, я должен был упомянуть об этом. Или есть способ, с помощью которого я могу легко получить доступ к их именам позже? –

+0

Правильно, нет причин, по которым вы не могли бы сохранить Гиды в словаре , чтобы потом получить доступ к текстовым полям (я задаюсь вопросом, почему я получил нисходящее второе место после того, как я разместил это, хотя ...) – Icepickle

+0

Это wasn «Я ниспослал это, я не могу спуститься вниз, пока у меня не будет хорошей репутации. Не могли бы вы объяснить, как создать Guid, а затем добавить его в словарь? Нужно ли мне создавать словарь вне цикла for и что именно делает словарь? Спасибо –

0

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

// a field 
List<TextBox> ingredientTextBoxes = new List<TextBox>(); 

private void Populate(int ingredientCount) 
{ 
    for (i = 1; i < ingredientCount; i++) 
    { 
     // Assign a consecutive name so can order by it 
     TextBox tb = new TextBox { Name = "IngredientTextbox" + i}; 
     ingredientTextBoxes.Add(tb); 
    } 
} 

// when you want the ingredients 
public List<string> GetIngredients 
{ 
    List<string> ingredients = new List<string>(); 

    foreach (var tb in ingredientTextBoxes) 
    { 
     ingredients.Add(tb.text); 
    } 

    return ingredients; 
} 

// contains 
private List<string> GetIngredientsMatching(string match) 
{ 
    // Contains really should take a StringComparison parameter, but it doesn't 
    return ingredientTextBoxes 
        .Where(t => t.Text.ToUpper().Contains(match.ToUpper())) 
        .Select(t => t.Text); 
} 

Edit: если вы собираетесь иметь несколько значений для каждого ингредиента, то использовать пользовательский элемент управления, который выставляет свойства, которые вы хотите - суммируя количество, вес, описание (например, «щепотку» соли) - в наиболее удобный способ для кода доступа к этим свойствам.

+0

Спасибо, я думаю, что это идеальное решение, которое я искал. Очень ценю, к сожалению, я не могу выдвигать, но в противном случае я бы это сделал. Но еще одна вещь, как бы я тогда прочитал эту строку? Позже в программе мне нужно будет использовать .Contains(), так как бы я мог обратиться к отдельной строке для этого? –

+0

@KieranWarren текст всегда доступен непосредственно из элементов управления текстовым полем, и вы храните их в списке. См. Править. Хотя вы не можете голосовать, если это ответ на ваш вопрос, вы можете отметить его как таковой, нажав галочку рядом с ответом. – stuartd