2012-12-12 3 views
1

У меня есть мои Form1 и мой Form2.
Мой Form1 имеет метод, доступ к методу, который добавляет узлы это TreeView:Способ и контроль доступа к другим классам

private void AddNode(TreeNode node) 
{ 
    treeView1.Nodes.Add(node); 
} 

Я хочу получить доступ этот метод из моего Form2 но я вроде застрял на то, что

  • Статический метод AddNode потребует статического дерева TreeView1, который является довольно плохой практикой.
  • Новый экземпляр Form2 внутри Form1 создаст другой экземпляр treeView1, который не является тем, что я хочу.

Также treeView1 объявлен внутри конструктора, так что я не могу изменить его модификатор статику (мне сказали, что это не очень хорошая идея, чтобы положить статические элементы управления внутри вашей формы).

Любая идея, как я могу это сделать?

+0

Почему бы вам просто не объявить AddNode открытым (не статическим) и передать ссылку Form1 на Form2? Например, используя публичное свойство типа Form1. –

+0

Форма 1 является основной формой? Вы начинаете Form2 из Form1? –

+0

@lazyberezovsky нет, они оба созданы из двух других форм. Мне сложно передать treeview в качестве параметров также конструктор form2, но в то время это не видно – phadaphunk

ответ

3

Я думаю, что лучший вариант создает событие в Form2 и подписаться на это событие в Form1. Когда вы делаете что-то на Form2 (например, кнопки пользовательских кликов), поднимите это событие (также вы можете передать некоторые параметры в качестве аргумента события).

Form1:

private void StartForm2Button_Click(object sender, EventArgs e) 
{ 
    Form2 form2 = new Form2(); 
    form2.SomethingHappened += Form2_SomethingHappened; 
    form2.Show(); 
} 

private Form2_SomethingHappened(object sender, EventArgs e) 
{ 
    Form2 form2 = (Form2)sender; 
    string data = form2.Data; 
    // create node 
    AddNode(node); 
} 

Form2:

public event EventHandler SomethingHappened; 

public string Data 
{ 
    get { return textBoxData.Text; } 
} 

private void SomeButton_Click(object sender, EventArgs e) 
{ 
    if (SomethingHappened != null) 
     SomethingHappened(this, EventArgs.Empty); 
} 

Update, таким образом, Вы хотите сказать, что формы, созданные из двух разных форм, то вам нужно какой-то другой способ, чтобы подписаться на Form2 события.Вы можете получить form2 из коллекции открываемых форм приложения. ИЛИ вы можете поделиться общим объектом между формами:

public class Model 
{ 
    public event Action<string> DataAdded; // subscribe to this event in form1 

    public void AddData(string data) // call this method in form2 
    { 
     if (DataAdded != null) 
      DataAdded(data); 
    } 
} 

Ну, в лучшем мире, я создал модель, которая будет иметь все данные, а только сообразила, что состояние модели на Form1.

+0

Я нахожу «EventHandler» особенно плохого типа для события. Я предпочитаю 'Action ', где 'T' - это любая информация, которую вы хотите передать из' Form2' в 'Form1' (или использовать не-общий, если ничего не требуется). Обычно вам не нужно передавать ссылку на себя как «отправителя» при этом, и если вы это сделаете, вы можете, по крайней мере, набрать ее, если вы используете «Action» вместо «EventHandler». Я даже не знаю, почему «EventHandler» выжил до тех пор, пока он есть. Кроме этого, отличный ответ. – Servy

+0

@Servy, почему бы не пройти 'EventArgs '? Также я думаю, что обработчик событий выжил из-за параметра 'sender'. И да, я нахожу крайне странный второй параметр «EventArgs» в не-generic «EventHandler». Но так все WinForms реализованы. –

+0

Вы * можете *, но это больше кода, больше работы, 'sender' по-прежнему является бесполезным параметром, он менее ясен и т. Д. Завершите все аргументы в класс' EventArgs', когда вы можете просто передать их всем как 1 , 2 или 3 разных аргумента. Если вам нужно передать более 3 вещей, что-то не так, и, возможно, вам просто нужно передать (строго типизированную) ссылку на 'sender'. В этом случае вы можете видеть, что события args всегда пусты. Зачем беспокоиться об этом, если он никогда не используется? Это раздутие кода, которое добавляет дополнительные накладные расходы новым читателям кода. – Servy

1

Ниже приведены некоторые параметры, требующие хранения ссылки где-нибудь. Это может быть не лучший вариант для ситуации (или это может быть в зависимости от вашей ситуации), но есть и другие альтернативы, которые вы отправили, так что сделайте выбор.


Одним из решений является вы можете просто статическую ссылку на экземпляр Form1, который вы хотите использовать.

static Form1 OpenForm1 = new Form1(); 

//in some other code 
OpenForm1.MyFunction(); 

Есть много других способов, главное ваша потребность обеспечить ваш экземпляр Form2 имеет ссылку на экземпляр Form1 каким-то образом.


Другой вариант, вы можете передать экземпляр при создании Form2:

как свойство, например ...

//create Form2 from some where else 
Form2 form2 = new Form2(); 
form2.ReferenceToForm1 = form1; 

//in form2 
public Form1 ReferenceToForm1 {get;set;} 

//when needed in form2 
ReferenceToForm1.MyFunction(); 
+0

Для вашего решения 1 создание статического экземпляра Form1 также приведет к созданию другого экземпляра моего TreeView тоже? Поэтому, если я получаю доступ к OpenForm1 из Form2, он не будет тем же деревом, что и Form1. – phadaphunk

+0

@PhaDaPhunk: Это будет тот же экземпляр, если вы используете тот же экземпляр формы1. Вместо того, чтобы использовать 'new Form1()' точно так же, как указано выше, вам нужно назначить фактический экземпляр form1 (где бы вы его не создали) в качестве значения 'OpenForm1'. – musefan

+1

«Есть много других способов, главное - ваша необходимость обеспечить, чтобы ваш экземпляр Form2 каким-то образом ссылался на ваш экземпляр Form1.« Нет, вы этого не сделаете, и вам действительно не следует. Это значительно увеличивает связь между двумя формами. Используя события, вы можете гарантировать, что дочерняя форма никогда не должна знать что-либо о ее родителе. – Servy

0

Объявите интерфейс и передать Form2 ссылку что-то, что реализует интерфейс.

Например:

public interface INodeAddable { 
    void AddNode(TreeNode node); 
} 

public class Form1 : INodeAddable 
{ 
    private void SomeMethod() 
    { 
     var f2 = new Form2(this); 
    } 

    public void AddNode(TreeNode n) 
    { 
     // add node to tree 
    } 
} 

public class Form2 
{ 
    private INodeAddable x; 
    public Form2(INodeAddable x) 
    { 
    this.x = x; 
    } 

    public void SomeEventHandler(object sender, EventArgs e) 
    { 
    x.AddNode(someNewNode); 
    } 
} 
+0

Форма2 не объявлена ​​внутри формы1 – phadaphunk

+0

@PhaDaPhunk Затем, где это объявлено? Есть ли форма, которая создает как 'Form1', так и' Form2', 'Form2' создает' Form1', или что? – Servy

+0

Они оба разделены (извините, я не объяснил это). Они оба созданы из двух разных форм, поэтому они не видят друг друга, когда объявляются (в противном случае я бы передал ссылку). – phadaphunk

0

Сделайте формы доступными друг к другу.

Поскольку вы сказали, что они созданы из разных форм, один из подходов состоял бы в том, чтобы иметь общий корень знания о своем существовании и сделать связь с их общим предком.

Лучший подход, который я могу придумать, если такое поведение будет чем-то, с чем вы столкнетесь в будущем, - это базовый EventAggregator, который вводится во все формы, и через это вы можете передавать сообщения от одного к другому без их плотной связи. С этим вы можете подписаться Form1 на событие, которое Form2 запускает, и когда это событие является triggerd, вы должны добавить узел.

Смежные вопросы