2013-02-25 3 views
0

У меня есть класс и форма. класс предназначен для выполнения некоторых процессов при поднятии события и возврата значений в форму только для отображения. У меня вроде бы проблемы передаются значения обратно в форму. Например, у меня есть этот код в классе print:Передача значения из другого класса в текстовое поле в форме?

public class PrintClass : Form1 
{ 

    public void printEventHandler(object sender, EventArgs e) 
    { 

     string text = "Process Completed"; 
     append_Tbox(text); 

    } 

} 

и метод в Form1 для отображения текста:

public void append_Tbox(string s) 
    { 

     TboxPrint.AppendText(s); 
    } 

Однако, ничего не отображается. Я считаю, что что-то не так, но я не могу понять это. Каков самый быстрый способ передать значения из класса в форму?

+0

Из кода, который вы предоставили, выглядит так, как append_Tbox fucntion находится в том же классе. Правильно ли я – Vikram

+0

@Vikram, класс 'PrintClass' наследует' form1', поэтому я могу напрямую вызвать этот метод. – Liban

+0

@ Liban - вы не можете получить доступ к TxtBox вне класса, потому что оба элемента управления Private, см. Designer.cs –

ответ

1

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

Правильный способ сделать это на самом деле намного проще. Вам просто нужно иметь свой другой класс возвращает значение от его методы:

public class PrintClass 
{ 
    public string DoWork() 
    { 
     Thread.Sleep(2000);//placeholder for real work. 
     return "Process Completed"; 
    } 
} 

Теперь ваша основная форма может просто вызвать этот метод и добавить возвращаемое значение в текстовое поле.

Как только вы сделаете это, у вас будет совершенно отдельная проблема. Если вы выполняете работу в потоке пользовательского интерфейса, вы будете блокировать этот поток пользовательского интерфейса во время работы, не позволяя перерисовать форму или какие-либо другие события от обработки. Вам нужно сделать работу в фоновом потоке, а затем вернуться к потоку пользовательского интерфейса, чтобы обновить пользовательский интерфейс с результатами. Есть несколько способов сделать это, но если у вас есть C# 5.0 с помощью await является самым простым:

public class Form1 : Form 
{ 
    private void SomeEventHandler(object sender, EventArgs args) 
    { 
     string result = await Task.Run(()=>new PrintClass().DoWork()); 
     TboxPrint.AppendText(result); 
    } 
} 

Если вам нужно решение на C# 4.0 вы можете использовать ContinueWith, который более или менее то, что выше будет переведено, но это не так чисто от синтаксиса.

public class Form1 : Form 
{ 
    private void SomeEventHandler(object sender, EventArgs args) 
    { 
     Task.Factory.StartNew(()=>new PrintClass().DoWork()) 
      .ContinueWith(t => TboxPrint.AppendText(t.Result) 
       , CancellationToken.None 
       , TaskContinuationOptions.None 
       , TaskScheduler.FromCurrentSynchronizationContext()); 
    } 
} 
+0

в методе 'SomeEventHandler', какое событие он обрабатывает? кстати, в мысли, что в C# 4.0 нет 'await'. – Liban

+0

@Liban. Какое бы событие вы ни хотели, чтобы эта работа была выполнена; это не имеет большого значения. Есть только одно событие, с которым вы имеете дело, от его звука. Вы правы, в C# 4.0 нет 'await', поэтому я сказал, что вы можете сделать это, если используете C# 5.0. – Servy

+0

Есть ли альтернатива для 'Task.Run'? потому что он дает ошибку: «System.Threading.Tasks.Task» не содержит определения для «Run». возможно, он не существует C# 4.0. Я пытался искать другие варианты, но я не мог. – Liban

0

У меня есть создать делегат в Main Form

public delegate void LoginDelegate(string s); 

public partial class AirLineReservationMDI : Form 
    { 
     LoginDelegate loginAirLineDelegate; 

    } 

loginAirLineDelegate = new LoginDelegate(DisableToolStripMenuItems); 


public void DisableToolStripMenuItems(string s) 
     { 
      this.viewToolStripMenuItem.Visible = true; 
      this.bookingToolStripMenuItem.Visible = true; 
      this.existingUserToolStripMenuItem.Visible = false; 
      this.newUserToolStripMenuItem.Visible = false; 
      this.toolStripStatusUserID.Text = "USerID :- "+s;    
      this.LoginUserId = s; 
     } 

в другом классе, (я сдал объект delagete к этому классу) Я уволил делегат

logDelegate(textBoxUserName.Text); 
+0

Это не сработает, так как делегат все равно будет действовать на неправильном экземпляре формы. – Servy

+0

Servy- Я использовал Delagete для выполнения этих действий. ему нужно установить TxtValue из другого класса, лучшим и простым вариантом является Deleagte, мы используем делегат для достижения этой функциональности. –

+0

Вы вообще не обратились к моему комментарию; вы только что указали несколько несвязанных фактов, которые на самом деле ничего не значат. В этом случае использование делегата ничем не отличается от прямого вызова метода напрямую, который не работает для него. Этот ответ не помогает и не затрагивает основные проблемы, с которыми сталкивается ОП. – Servy

0

Я использовал Action<T> делегата, чтобы решить эту проблему. вот код, и он отлично работает.

class PrintClass 
{ 
    public Action<string> DisplayDelegate; 


    public void printEventHandler(object sender, EventArgs e) 
    { 
     string text = "Event Handled, and text value is passed"; 

     var copy = DisplayDelegate; 

     if (copy != null) 
     { 
      copy(text); 
     } 
    } 

} 

и в `Form1.cs':

private void Form1_Load(object sender, EventArgs e) 
    { 
     PrintClass p = new PrintClass(); 
     BtnPrint.Click += p.printEventHandler; 

     //subscrite the displayevent method to action delegate 
     p.DisplayDelegate += DisplayEvent; 

    } 


    public void DisplayEvent(string s) 
    { 

     Invoke(new Action(() => TboxPrint.AppendText(s))); 
    } 

поэтому текст 'Event обрабатывались, и текст передается значение' отображается на текстовом поле.

Я не уверен, что это эффективный способ. Спасибо, ребята.

+0

Выполняется ли ваш * актуальный * обработчик события печати для запуска? Это на самом деле ничего не делает, но если истинное событие потратит значительное количество времени на обработку, тогда эта работа будет блокировать поток пользовательского интерфейса, что является проблемой. Кроме того, если вы используете это, вы должны использовать 'event', а не сырой делегат. Просто используйте 'public event Action DisplayDelegate;' вместо этого в 'PrintClass'. Вероятно, вы также должны называть его чем-то более похожим на «PrintCompleted», а не «DisplayDelegate», поскольку это более точно указывает, что это такое. – Servy

+0

Вы правы. он блокирует поток пользовательского интерфейса. Спасибо за разъяснения. это действительно помогло мне понять суть. – Liban

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