[英]Changing the Label1.Text of Form1 from Form2 Button1_Click in C#
我正在嘗試通過從Form2
觸發的Button1_Click
更改我的Form1
(所有者)上的Label1.Text
,但Label1.Text
沒有任何更改。 它仍然是空字符串(“”)。 我已經兩次/三次檢查了我的代碼。 我找不到任何問題。
這是我到目前為止所做的:
Form1
// Label1 is inside the TabControl Page 0
// Label1.Modifier property already set to public
// and Label1.Text = ""
public static FrmOwner Self;
public FrmOwner()
{
InitializeComponent();
Self = this;
}
private void Button2_Click()
{
FrmForm2 frm = new FrmForm2 ();
frm.ShowDialog();
}
Form2
public FrmForm2()
{
InitializeComponent();
}
private void Button1_Click(object sender, EventArgs e)
{
FrmOwner.Self.Label1.Text = "Changed Text";
}
我確定我的代碼肯定有問題。 請幫忙。
您可以將 Form1 實例傳遞給 Form2。 然后從 From2 訪問 From1 的公共方法和屬性。
表格1
public static FrmOwner Self;
public FrmOwner()
{
InitializeComponent();
Self = this;
}
private void Button2_Click()
{
FrmForm2 frm = new FrmForm2 (this);
frm.ShowDialog();
}
public void SetLabel(string txt)
{
Label1.Text = txt
}
表格2
private FrmForm1 _frm1;
public FrmForm2(FrmForm1 frm1)
{
_frm1 = frm1;
InitializeComponent();
}
private void Button1_Click(object sender, EventArgs e)
{
_frm1.SetLabel("New Text");
}
有幾種方法可以做到這一點。 傳遞您想要訪問的表單或控件/變量可能是最好的方法,因為它不會不必要地公開傳遞的控件/變量,並且所有內容都可以保密。
但是,如果您選擇以第一種形式公開控件/變量,這可以簡化。 在此示例中,form1 中的Label
控件label1
似乎是我們希望在 form2 中訪問的內容。 因此,一個非常簡單的方法是利用Forms
Owner
屬性,它應該如下所述工作。
首先,我們希望通過將 Form1 的Modifier
屬性設置為public
來公開 form1 的Label
... label1
控件。
然后,當Form1
創建並顯示Form2
時……我們希望通過利用Forms
Owner
屬性將Form1
傳遞給Form2
,這通過在調用Form2
的Show
或ShowDialog
時將Owner
表單簡單地傳遞給Form2
來完成。 像下面的東西......
Form2 f2 = new Form2();
f2.Show(this);
調用Show/ShowDialog
方法時,請注意this
作為參數。 這就是我們在第一種形式中需要做的所有事情。 Show/ShowDialog
中的this
參數會將被調用表單的Owner
屬性設置為通用Form
,我們稍后可以將其轉換為被調用表單中的Form1
對象。
然后在第二個Form2
中,當我們想要訪問Form1
publicly
的label1
……我們只需要將 form2 的Owner
屬性轉換為Form1
對象,因為Owner
是一個“通用” Form
對象。 所以,這看起來像……
private void button1_Click(object sender, EventArgs e) {
((Form1)Owner).label1.Text = "Hello from form2";
}
這就是所有需要的。
我一直很感興趣,到目前為止,我最同意的答案是 Enigmativity,但我覺得它還不足以將Form2
的實現與Form1
的實現分離。 我的建議是更接近MVVM設計模型,人們可以使用它來使代碼更易於維護和移植(例如,從長遠來看,我們可能希望有一天會制作這個應用程序的 iOS 和 Android 版本)。
考慮這個具有兩個(到目前為止)可綁定屬性Visible
和BindableText
的Form2
,並在其中任何一個發生更改時發送通知。 現在, Form2
上的Button
在單擊時作用於BindableText
屬性。
public partial class Form2 : Form, INotifyPropertyChanged
{
public Form2() => InitializeComponent();
private void buttonChangeText_Click(object sender, EventArgs e) =>
BindableText = $"Clicks = {_count++}";
static int _count = 1;
string _BindableText = string.Empty;
public string BindableText
{
get => _BindableText;
set
{
if(!Equals(_BindableText, value))
{
_BindableText = value;
OnPropertyChanged();
}
}
}
protected override void OnVisibleChanged(EventArgs e)
{
if (Visible && (Owner != null))
{
Location = new Point(
Owner.Location.X + Owner.Width + 10,
Owner.Location.Y
);
}
OnPropertyChanged(nameof(Visible));
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
同時,主窗體Form1
的簡化版本可能如下所示:
當復選框變為 true 時,會在顯示新實例之前附加PropertyChanged
事件。 然后,類似於 JohnG 的回答,我們調用ShowDialog(owner: this)
來分配Owner
屬性。 在OnVisibleChanged
覆蓋中,它的Location
用於設置彈出窗口顯示時的相對位置。
private void checkBoxShowForm2_CheckedChanged(object sender, EventArgs e)
{
if (((CheckBox)sender).Checked)
{
using (var form2 = new Form2())
{
form2.PropertyChanged += (sender, e) =>
{
switch (e.PropertyName)
{
case nameof(form2.BindableText):
label1.Text = form2.BindableText;
break;
case nameof(form2.Visible):
checkBoxShowForm2.Checked = form2.Visible;
checkBoxShowForm2.Enabled = !form2.Visible;
break;
}
};
form2.ShowDialog(owner: this);
}
}
}
當屬性發生變化時, Form1
會以它認為合適的方式做出響應:
BindingText
改變時設置private label1
的Text
屬性Visible
屬性變為 false 時,取消選中private checkBoxShowForm2
。 但是,重要的是,如果Form2
未來對其內部實現細節進行更改,則Form1
不會受到影響。
注意:Form2 需要處理
CharithJ 和 Enigmativity 的答案將受益於using
語句,以防止ShowDialog
調用中的資源泄漏。 Form.ShowDialog Method的官方 Microsoft 文檔指出,此處需要 using 塊(或其他處置方法):
因為顯示為對話框的窗體是隱藏的而不是關閉的,所以當您的應用程序不再需要該窗體時,您必須調用該窗體的 Dispose 方法。
它是這樣設計的,以便Form2
可以移動,而不是一個局部變量,它可以是member ,實例化一次,並顯示關閉多次。 這樣的事情是可能的,因為它沒有處理它的Handle
(當Form1
處理時仍然需要處理它)。 但由於它目前被用作本地,它需要using
。
另一方面,JohnG 在Form2
的本地新實例上使用Show(this)
將釋放句柄,但不會是模態的。 也就是說,它將在 Z 順序中保持在其所有者Form1
的頂部,但不會阻止用戶與Form1
的交互。
更慣用的方法是使用事件。
表格1
public class FrmForm1 : Form
{
private void Button2_Click()
{
FrmForm2 frm = new FrmForm2();
frm.LabelUpdated += FrmForm2_LabelUpdated;
frm.ShowDialog();
}
private void FrmForm2_LabelUpdated(object sender, string txt)
{
Label1.Text = txt
}
}
窗體2
public class FrmForm2 : Form
{
public event EventHandler<string> LabelUpdated;
private void Button1_Click(object sender, EventArgs e)
{
this.LabelUpdated?.Invoke(this, "New Text");
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.