Arm*_*nAH 1 c# user-controls winforms
因此,我有一个用作导航栏的主窗体和两个显示一些控件的用户控件。
我UserControlsA有一些需要填写的字段。使用这些数据,我创建了一个包含一些信息的对象。我需要将该对象传递给,UserControlsB以便我可以在那里显示一些数据。
我的想法是创建该对象的三个实例,一个在 中UserControlsA用于获取该对象所需的信息,一个在主窗体中用于从 中获取该对象的“副本” UserControlsA,一个在其中UserControlsB可以从主窗体中获取信息形式。
然而,这似乎是多余的,甚至不起作用。这是一些代码:
主要形式:
public partial class main : Form
{
public Object object { get; set; }
public UCA uca;
public UCB ucb;
public Form1()
{
InitializeComponent();
uca = new UCA();
ucb = new UCB();
panel2.Controls.Add(uca);
panel2.Controls.Add(ucb);
ucb.Visible = false;
uca.Visible = true;
}
private void button1_Click(object sender, EventArgs e)
{
ucb.Visible = false;
uca.Visible = true;
}
private void button2_Click(object sender, EventArgs e)
{
ucb.Visible = true;
uca.Visible = false;
}
}
Run Code Online (Sandbox Code Playgroud)
用户控件A:
public partial class UCA : UserControl
{
public Object object { get; set; }
public UCA()
{
InitializeComponent();
}
private void bUsage_Click(object sender, EventArgs e)
{
//Data is provided
object = new Object(data);
//I use var parent to try and access the object from the main form.
var parent = Parent as Form1;
object = parent.object;
}
}
Run Code Online (Sandbox Code Playgroud)
用户控制B:
public partial class UCB : UserControl
{
public Object object { get; set; }
public UCB()
{
InitializeComponent();
}
public void updateData()
{
//I try to assign the object from the main form to this form's object.
var parent = Parent as Form1;
object = parent.object;
}
}
Run Code Online (Sandbox Code Playgroud)
使用 var Parent 不起作用。我能做些什么?
几个使用INotifyPropertyChanged接口的示例以及使用标准公共事件的实现。
\n相关文档:
\n Windows 窗体数据绑定
\n Windows 窗体数据绑定中的更改通知
\n与数据绑定相关的接口
使用INotifyPropertyChanged:
\nUserControl 公开一个公共属性(这里,在第一个示例中名为CustomDataObject简单类型,在第二个示例中。当然它可以是其他类型)。\n该属性用Bindable属性修饰。这里更多的是意图的描述,没有附加模板。\n添加了另外两个标准属性:stringobjectBindingDirection
接口INotifyPropertyChanged可以被视为一种简化的方法,使用相同的事件处理程序将属性绑定添加到多个属性,以通知值的更改。
\n接口的默认实现只需要将PropertyChangedEventHandler类型的公共事件添加到类中。
\n当属性值更改时,设置器仅调用事件。执行此操作的方法略有不同;这里我使用的OnPropertyChanged()方法使用CallerMemberName属性来获取调用它的属性的名称。它在 WinForms 和 WPF 中相当常见。
UCA UserControl:
\nUserControl(请参阅可视示例)有两个可更改绑定属性CustomDataObject值的按钮。他们的Click行动由 处理 ButtonsAction_Click。
using System.ComponentModel;\nusing System.Runtime.CompilerServices;\nusing System.Windows.Forms;\n\npublic partial class UCA : UserControl, INotifyPropertyChanged\n{\n public event PropertyChangedEventHandler PropertyChanged;\n private string m_DataObject = string.Empty;\n\n public UCA() => InitializeComponent();\n\n [Bindable(true, BindingDirection.TwoWay), DefaultValue("")]\n [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]\n public string CustomDataObject {\n get => m_DataObject;\n set {\n if (m_DataObject != value){\n m_DataObject = value;\n OnPropertyChanged();\n }\n }\n }\n\n private void OnPropertyChanged([CallerMemberName] string propertyName = "") =>\n PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));\n\n private void ButtonsAction_Click(object sender, EventArgs e)\n {\n var btn = sender as Button;\n CustomDataObject = (btn == SomeButton) ? txtInput1.Text : txtInput2.Text;\n }\n}\nRun Code Online (Sandbox Code Playgroud)\nUCB UserControl :
\n这个另一个 UserControl 是接收者。它只是公开了一个ReceiverDataObject将绑定到CustomDataObjectUCA 属性的公共属性 ( )。
该ReceiverDataObject属性也被定义为[Bindable],目的是使其仅是单向的。该属性不会引发任何事件。它接收一个值,将其存储在私有字段中并设置内部 UI 元素。
public partial class UCB : UserControl\n{\n private string m_RecvDataObject = string.Empty;\n\n public UCB() => InitializeComponent();\n\n [Bindable(true, BindingDirection.OneWay)]\n [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]\n public string ReceiverDataObject {\n get => m_RecvDataObject;\n set {\n m_RecvDataObject = value;\n txtPresenter.Text = m_RecvDataObject;\n }\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n使用标准事件通知:
\n您还可以使用标准事件生成属性更改通知。
\n不同之处在于,每个属性都需要一个事件来通知更改。
\n如果您已经为此使用了事件委托,那么它可能是一个不错的选择,因为需要添加的内容很少:只需调用在属性设置器中引发事件的受保护方法即可。
在这里,我使用常见的 .Net 事件处理,使用由底层 Component 类定义并由其Events属性公开的EventHandlerList来添加删除事件订阅。\n事件通常是通过调用与事件同名(前缀除外)的受保护方法来引发的。\n这里,Event =>方法。OnCustomDataObjectChangedOnCustomDataObjectChanged()
\n您可以在所有标准控件中看到这种模式。
\xe2\x96\xb6CustomDataObjectChanged分配给事件的名称不是一个选择:该事件必须具有与属性相同的名称和后缀Changed。
\n这就是模式,遵循它就足够了。
UCA用户控制:
\npublic partial class UCA : UserControl\n{\n private static readonly object Event_CustomDataObjectChanged = new object();\n private object m_DataObject = null;\n\n public UCButtonActions() => InitializeComponent();\n\n [Bindable(BindableSupport.Yes, BindingDirection.TwoWay), DefaultValue(null)]\n [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]\n public object CustomDataObject {\n get => m_DataObject;\n set {\n if (m_DataObject != value){\n m_DataObject = value;\n OnCustomDataObjectChanged(EventArgs.Empty);\n }\n }\n }\n\n public event EventHandler CustomDataObjectChanged {\n add {\n Events.AddHandler(Event_CustomDataObjectChanged, value);\n }\n remove {\n Events.RemoveHandler(Event_CustomDataObjectChanged, value);\n }\n }\n\n protected virtual void OnCustomDataObjectChanged(EventArgs e)\n {\n if (Events[Event_CustomDataObjectChanged] is EventHandler evth) evth(this, e);\n }\n} \nRun Code Online (Sandbox Code Playgroud)\nUCB 用户控制:
\n第二个 UserControl 不变。这只是接收器。
Form 类(或用作 Handler 的另一个类):
\n在表单构造函数或表单初始化后调用的任何其他方法中,使用DataBindings属性来链接两个 UserControl 的属性:
\npublic SomeForm()\n{\n InitializeComponent();\n ucb1.DataBindings.Add("ReceiverDataObject", uca1, "CustomDataObject", \n false, DataSourceUpdateMode.OnPropertyChanged);\n}\nRun Code Online (Sandbox Code Playgroud)\n您还可以使用 BindingSource 进行调解:
\nBindingSource ucsSource = null;\n\npublic SomeForm()\n{\n InitializeComponent();\n ucsSource = new BindingSource(uca1, null);\n ucb1.DataBindings.Add("ReceiverDataObject", ucsSource, "CustomDataObject", \n false, DataSourceUpdateMode.OnPropertyChanged);\n}\nRun Code Online (Sandbox Code Playgroud)\n示例功能:
\n\n| 归档时间: |
|
| 查看次数: |
787 次 |
| 最近记录: |