hi guys . I thought it would be easy to call a combobox(or anything else ) from another form but I'm getting some problems .
I have a form named "Sale" and another form named "Factor" . there's a label on the factor form that I want to be valued by the combobox on the sale form . I wanted to write the code as below , but it seems it's not correct :
Sale sale = new Sale();
label.Text = Sale.cmbBox.Text;
Many folks starting out tend to try to read one form's (or dialog's) controls from another dialog. For simple forms and beginner programmers, that's great because it allows the dev to get his work done.
The problem is that for complex forms, you create code that is tightly coupled and if you change the type of control used to display the data, then you will break any child forms that use the control to access the data.
A better way is to expose data properties that allow child form access (but on the data level, not the control level).
The child form gets access to the parent data by getting passed a reference to the parent form.
I should mention that this approach isn't the absolute best way because the child controls are somewhat tightly coupled to the fact that they get their data from another form.
An even better way would be to pass a model or view model to all the Forms using one of the MVC, MVP, or MVVM design patterns. This is the preferred approach in WPF, but it takes more work to setup and understand.
So to answer your question, let's just go one step better and expose data properties that the child Factor Form can access.
Let's start by creating a Sales form. This form has a ComboBox drop list with some Region data in it (Northern, Eastern, Southern, & Western). We'll force the user to select a region before allowing the user to click on a Factor button. This button will open the FActor form. The sales form will also expost a FactorType readonly textbox. This data will get set by the factor form (and updated only if the user clicks OK in the factor form).
When the user clicks the Factor button in the Sales form, we pass the 'this' pointer of the sales class to the Factor constructor. This gives the Factor form access to the Sales class public properties. Again, we don't give access to the controls of the Sales form, but only expose public data properties. As mentioned, this helps reduce coupling between forms.
When the Factor form opens, it retrieves the region data from the SelectedRegion property and displays the data. The Factor form also has a FactorType textbox that gets passed back to the Sales.FactorData property if the user clicks the OK button in the Factor form. If the Factor.Cancel btn is pressed, the FactorType data doesn't get updated.
Sales form code:
Code:
namespace OrderSystem
{
#region Using Directives
using System;
using System.Windows.Forms;
#endregion Using Directives
public partial class Sale : Form
{
public Sale( )
{
InitializeComponent( );
}
#region Public Properties (Notice how we don't expose the controls directly)
/// <summary>
/// Public FactorType property.
/// </summary>
public string FactorType
{
get { return _textBoxFactorType.Text; }
set { _textBoxFactorType.Text = value; }
}
/// <summary>
/// Selected Region property.
/// </summary>
public string SelectedRegion
{
// The seleted item is the Region string.
// For a real project, we would want to bind the combobox
// to a collection, and retrieve the selected item and
// its associated value. This would allow to display
// different selections (such as localized strings), and
// keep the programmatic values separate.
get { return _comboBoxRegion.SelectedItem as String; }
}
#endregion Public Properties
// Open the Factor Form
private void _buttonFactor_Click( object sender, EventArgs e )
{
// Pass in the 'this' pointer to all the Factor
// form to access the data in this form.
if ( DialogResult.OK == Factor.ShowDlg( this ) )
{
// Not used here, but additional operations could
// be performed by
}
}
// Prevent the Factor form from getting opened by disabling
// the Factor button until a region has been selected
private void _comboBoxRegion_SelectedIndexChanged(object sender, EventArgs e)
{
_buttonFactor.Enabled = (_comboBoxRegion.SelectedIndex != -1);
}
}
}
Factor Form code:
Code:
namespace OrderSystem
{
#region Using Directives
using System.Windows.Forms;
#endregion Using Directives
public partial class Factor : Form
{
public static DialogResult ShowDlg(Sale sale)
{
var dlg = new Factor( sale );
return dlg.ShowDialog( );
}
public Factor( Sale sale )
{
InitializeComponent();
_sale = sale;
_textBoxRegion.Text = _sale.SelectedRegion;
_textBoxFactorType.Text = _sale.FactorType;
}
private void _buttonOk_Click(object sender, System.EventArgs e)
{
_sale.FactorType = _textBoxFactorType.Text;
Close( );
}
private readonly Sale _sale;
}
}
It might seem like exposing the controls would be the fastest way (and it would be). It doesn't mean that that would be the best way. It's worth the time to understand an approach that leads to looser coupling.
thanks , I made it public but compiler doesn't get errors but it doesn't work at all .
here's my code:
Sale sale = new Sale();
MessegeBix.Show(sale.cmbBox1.Text);
cmbBox1has no items or its null. It needs to have an item selected for the Text prop. to work. Its best to set any label's value through a get\set function in the constructor, and then use it appropriate.
* The Best Reasons to Target Windows 8
Learn some of the best reasons why you should seriously consider bringing your Android mobile development expertise to bear on the Windows 8 platform.