I am trying to change what is visible in my user control by checking some checkbox's in my form (the parent). I have tried changing it directly in the parent form and in a function on the child's side. From debug the property is being changed but then after the call the property seems to reset to the default value.
My code on the parent side
public partial class Program: DevExpress.XtraBars.Ribbon.RibbonForm
{
public Program()
{
InitializeComponent();
}
public class GlobalVariables
{
public static string categoryID = "1";
public static string currentPage = "Campus";
}
private void ribbonControl1_MouseDown(object sender, MouseEventArgs e)
{
RibbonControl ribbon = sender as RibbonControl;
RibbonHitInfo hitInfo = ribbon.CalcHitInfo(e.Location);
if (hitInfo.HitTest == RibbonHitTest.PageHeader)
{
System.Diagnostics.Debug.WriteLine(hitInfo.Page.Name + "");
pnlPanel.Panel2.Controls.Clear();
if(hitInfo.Page.Name == "Campus")
{
var Campus = new WindowsFormsApplication1.Campus();
pnlPanel.Panel2.Controls.Add(Campus);
GlobalVariables.currentPage = "Campus";
}
else if (hitInfo.Page.Name == "Report")
{
var Report = new WindowsFormsApplication1.Report();
pnlPanel.Panel2.Controls.Add(Report);
GlobalVariables.currentPage = "Report";
}
else if (hitInfo.Page.Name == "Admin")
{
var Admin = new WindowsFormsApplication1.Admin();
pnlPanel.Panel2.Controls.Add(Admin);
GlobalVariables.currentPage = "Admin";
}
}
}
private void Program_Load(object sender, EventArgs e)
{
var Campus = new WindowsFormsApplication1.Campus();
pnlPanel.Panel2.Controls.Add(Campus);
List<string> Category = GenerateCategory();
for(int j = 0; j<= Category.Count(); j++)
{
krpList.Items.Add(Category[j + 1]);
krpValue.Items.Add(Category[j]);
j++;
}
}
public void krpList_SelectedIndexChanged(object sender, EventArgs e)
{
int selectedIndex = krpList.SelectedIndex;
krpValue.SelectedIndex = selectedIndex;
GlobalVariables.categoryID = krpValue.SelectedItem + "";
System.Diagnostics.Debug.WriteLine(krpValue.SelectedItem);
Reset();
}
public void Reset()
{
var Campus = new WindowsFormsApplication1.Campus();
pnlPanel.Panel2.Controls.Clear();
pnlPanel.Panel2.Controls.Add(Campus);
}
private void chkDisplay_EditValueChanged(object sender, EventArgs e)
{
string displayInfo = "";
var Campus = new WindowsFormsApplication1.Campus();
displayInfo = chkDisplay.Text;
Campus.UpdateAudit(displayInfo);
Campus.treeList1.ClearNodes();
}
}
}
User control code
public void UpdateAudit(string displayInfo) //Child Method
{
treeList1.ClearNodes(); //Adjusting property on user control element
treeList1.Columns[1].VisibleIndex = 1;
treeList1.Columns[2].VisibleIndex = 2;
//...more code similar to above
}
Any help would be appreciated.
well, here is the problem, you are using multiple instances of same form.
you should rather create a single instance and use it .
public partial class Program: DevExpress.XtraBars.Ribbon.RibbonForm {
UserControl Campus = null;
public Program()
{
InitializeComponent();
Campus = new WindowsFormsApplication1.Campus();
}
private void Program_Load(object sender, EventArgs e) {
// remove this object creation
//var Campus = new WindowsFormsApplication1.Campus();
pnlPanel.Panel2.Controls.Add(Campus);
...
}
public void Reset() {
// remove this object creation
// var Campus = new WindowsFormsApplication1.Campus();
}
private void chkDisplay_EditValueChanged(object sender, EventArgs e) {
string displayInfo = "";
// remove this object creation
// var Campus = new WindowsFormsApplication1.Campus();
}
private void ribbonControl1_MouseDown(object sender, MouseEventArgs e)
{
...
if(hitInfo.Page.Name == "Campus")
{
// remove this object creation
//var Campus = new WindowsFormsApplication1.Campus();
}
...
}
}
Related
I'm very new to programming and I am writing a short hangman game for my programming class, I have two private voids, one when you change the text in the textbox for the correct answer and one for when you guess a character. I need to transfer the variable "svar" from the first instance to the other, when I try to use the variable "svar" in the second instance I get the error message "The name "svar" does not exist in the current context"
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void TbxSvar_TextChanged(object sender, EventArgs e)
{
if (tbxSvar.TextLength == 6)
{
pbxGubbe.Top = 6;
tbxVisa.Text = "??????";
tbxGissa.Enabled = true;
string svar = tbxSvar.Text;
tbxSvar.Text = "";
}
else
{
tbxVisa.Text = "";
}
}
private void TbxGissa_TextChanged(object sender, EventArgs e)
{
if (tbxGissa.Text == "") return;
string gissning = tbxGissa.Text;
int index = svar.indexOf(gissning);
}
}
You have defined svar as a variable in a method so it won't be visible elsewhere (unless you pass it as a method argument). Instead define it as a field in your class.
public partial class Form1 : Form
{
string svar; // <----------- place here. Now it is a 'field'
public Form1()
{
InitializeComponent();
}
private void TbxSvar_TextChanged(object sender, EventArgs e)
{
if (tbxSvar.TextLength == 6)
{
pbxGubbe.Top = 6;
tbxVisa.Text = "??????";
tbxGissa.Enabled = true;
svar = tbxSvar.Text; // <---------- use svar here
tbxSvar.Text = "";
}
else
{
tbxVisa.Text = "";
}
}
private void TbxGissa_TextChanged(object sender, EventArgs e)
{
if (tbxGissa.Text == "") return;
string gissning = tbxGissa.Text;
int index = svar.indexOf(gissning); // <---------- ...and here
}
}
I appear to have all of the things necessary for Drag-n-Drop to be working, yet my code is not called when I attempt to drag something from one control to another.
I created a Test Class to use to create data:
class TestClass
{
public TestClass()
{
Name = "Blank";
Id = -1;
}
public String Name { get; set; }
public int Id { get; set; }
public object Data { get; set; }
public override String ToString()
{
return String.Format("{0}: {1}", Id, Name);
}
}
I created an empty form with 2 List View controls, listView1 and listView2:
I created event handlers for all of the Drag-n-Drop methods and put breakpoints on them:
private void Form_DragDrop(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.Copy;
if (e.Data.GetDataPresent(typeof(TestClass)))
{
var item = e.Data.GetData(typeof(TestClass)) as TestClass;
if (item != null)
{
// ?
}
}
}
private void Form_DragEnter(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.Copy;
if (sender.Equals(listView2))
{
e.Effect = DragDropEffects.All;
if (e.Data != null)
{
var format = GetString(e);
Console.WriteLine("{0} has a(n) {1} entering it.", listView2.Name, format);
}
}
}
private void Form_DragLeave(object sender, EventArgs e)
{
if (sender.Equals(listView2))
{
}
}
private void Form_DragOver(object sender, DragEventArgs e)
{
// Code Project Article 9017 says DragOver fires repeatedly, even if the mouse does not move.
if ((e.X != _lastX) || (e.Y != _lastY))
{
_lastX = e.X;
_lastY = e.Y;
if (e.Data.GetDataPresent(typeof(TestClass)))
{
}
else
{
e.Effect = DragDropEffects.None;
}
}
}
private void Form_GiveFeedback(Object sender, GiveFeedbackEventArgs e)
{
if (sender.Equals(listView2))
{
// ?
}
}
private void Form_QueryContinueDrag(object sender, QueryContinueDragEventArgs e)
{
var listView = sender as ListView;
if (listView != null)
{
}
}
private String GetString(DragEventArgs e)
{
var result = String.Empty;
if ((e.AllowedEffect & DragDropEffects.Copy) == DragDropEffects.Copy)
{
var formats = e.Data.GetFormats();
foreach (var format in formats)
{
Console.WriteLine("Data is in the format of [{0}].", format);
result = format;
}
}
return result;
}
I wired both controls up after the constructor's InitializeComponent();:
public ListViewsForm()
{
InitializeComponent();
// Setup ListView 1:
listView1.AllowDrop = true;
listView1.DragDrop += Form_DragDrop;
listView1.DragEnter += Form_DragEnter;
listView1.DragLeave += Form_DragLeave;
listView1.DragOver += Form_DragOver;
listView1.GiveFeedback += Form_GiveFeedback;
listView1.QueryContinueDrag += Form_QueryContinueDrag;
listView1.Dock = DockStyle.Fill;
listView1.View = View.List;
// Setup ListView 2:
listView2.AllowDrop = true;
listView2.DragDrop += Form_DragDrop;
listView2.DragEnter += Form_DragEnter;
listView2.DragLeave += Form_DragLeave;
listView2.DragOver += Form_DragOver;
listView2.GiveFeedback += Form_GiveFeedback;
listView2.QueryContinueDrag += Form_QueryContinueDrag;
listView2.Dock = DockStyle.Fill;
// Create some data:
var group1 = new ListViewGroup("Known Colors");
foreach (KnownColor known in Enum.GetValues(typeof(KnownColor)))
{
var item = new TestClass()
{
Name = known.ToString(),
Id = (int)known,
Data = known,
};
var color = Color.FromKnownColor(known);
var lvi = new ListViewItem(item.ToString(), group1) {
BackColor = Color.FromArgb(color.ToArgb() ^ 0xffffff),
ForeColor = color,
Tag = item,
};
listView1.Items.Add(lvi);
}
}
Whenever I run the project, everything loads up fine, but any attempt to drag an item from the LEFT side to the RIGHT side does nothing. None of my break points are hit. Nothing happens.
What have I left out?
You are missing a handy event and the method that starts the dragging operation:
listView1.ItemDrag += listView1_ItemDrag;
void listView1_ItemDrag(object sender, ItemDragEventArgs e) {
DoDragDrop(e.Item, DragDropEffects.Copy);
}
So, I got kind of stuck over my head while I tried to program something new.
I'm trying to add objectBeer_pluche or objectBeer_Elektro to my OBJberenlijst on the Beren Main form from the details Form, so I can add both instances of 2 classes to the same list.
I'm not even sure this is possible by the way. So, I would like feedback if what I am trying to do is possible to start with. I already figured VOID is not right but I am really clueless here.
This is my main beren.cs form with an OBJberenlist, that's where I try to add objectBeer_pluche or objectBeer_Elektro into it:
public partial class Beren : Form
{
public interface Berenlijst { }
public List<Berenlijst> OBJberenLijst = new List<Berenlijst>();
public Beren()
{
InitializeComponent();
}
private void Beren_Load(object sender, EventArgs e)
{
}
private void BTNToevoegen_Click(object sender, EventArgs e)
{
this.Hide();
Details Details = new Details();
if (Details.ShowDialog(this) == DialogResult.OK)
{
OBJberenLijst.Add(Details.getdetails());
}
Details.Close();
Details.Dispose();
}
public void LijstLaden()
{
foreach(Beer berenobject in OBJberenLijst)
{
LST_beren.Items.Add(berenobject.Naam);
}
}
}
}
from this form called details.cs
public partial class Details : Form
{
public Details()
{
InitializeComponent();
BTN_toevoegen.DialogResult = DialogResult.OK;
BTN_cancel.DialogResult = DialogResult.Cancel;
}
private void Details_Load(object sender, EventArgs e)
{
RDB_pluche.Checked = true;
BTN_ok.Enabled = false;
}
private void RDB_pluche_CheckedChanged(object sender, EventArgs e)
{
PANEL_pluche.Visible = true;
PANEL_elektro.Visible = false;
}
private void RDB_elektro_CheckedChanged(object sender, EventArgs e)
{
PANEL_pluche.Visible = false;
PANEL_elektro.Visible = true;
}
private void BTN_toevoegen_Click(object sender, EventArgs e)
{
open_foto.Filter = "jpg (*.jpg)|*.jpg|bmp(*.bmp)|*.bmp|png(*.png)|*.png";
if (open_foto.ShowDialog() == System.Windows.Forms.DialogResult.OK && open_foto.FileName.Length > 0)
{
TXT_adres.Text = open_foto.FileName;
PIC_beer.Image = Image.FromFile(open_foto.FileName);
}
}
private void BTN_ok_Click(object sender, EventArgs e)
{
}
public void getdetails()
{
if (RDB_pluche.Enabled == true)
{
Pluche_Beer objectBeer_pluche = new Pluche_Beer(TXTNaam_pluche.Text, open_foto.FileName, "(Wasprogramma: " + TXT_wasprogramma.ToString() + " Graden Celsius");
}
else
{
Elektronische_Beer objectBeer_Elektro = new Elektronische_Beer(TXTNaam_elekro.Text, open_foto.FileName, "aantal Batterijen: " + CMBOBatterijen.ToString());
}
}
private void Details_MouseMove(object sender, MouseEventArgs e)
{
foreach (Control c in this.Controls)
{
if (c is TextBox)
{
TextBox textBox = c as TextBox;
if (textBox.Text != string.Empty)
{
BTN_ok.Enabled = true;
}
}
}
}
}
}
The problem is between this line...
OBJberenLijst.Add(Details.getdetails());
...and this line.
public void getdetails()
List.Add() requires an object to add, but getdetails() returns void. You probably want to change getdetails() to something like the following:
public Berenlijst getdetails()
{
if (RDB_pluche.Enabled == true)
{
return new Pluche_Beer(TXTNaam_pluche.Text, open_foto.FileName, "(Wasprogramma: " + TXT_wasprogramma.ToString() + " Graden Celsius");
}
return new Elektronische_Beer(TXTNaam_elekro.Text, open_foto.FileName, "aantal Batterijen: " + CMBOBatterijen.ToString());
}
Hopefully Pluche_Beer and Elektronisch_Beer inherent from Berenlijst. Otherwise you'll have to revise your logic in a broader way.
So I have this calculator http://gyazo.com/589156935eec141c3aedf83b9f960d29 (not enough reputation sorry)
When I type [1] and then [2] the display shows [12]
If I press a operator for example [+] the number 12 is still supposed to be shown in the display.
But, if I now start typing new numbers The old ones are supposed to be removed from the display. But i can't get this to work.
My form:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Miniräknare
{
public partial class Form1 : Form
{
Miniräknare miniräknare;
public Form1()
{
InitializeComponent();
miniräknare = new Miniräknare(0, 0, "", 0, false);
}
private void btnEquals_Click(object sender, EventArgs e)
{
tbxWindow.Text = miniräknare.doEquals();
}
private void btnNum1_Click(object sender, EventArgs e)
{
tbxWindow.Text = miniräknare.getOperand("1", tbxWindow.Text);
}
private void btnNum2_Click(object sender, EventArgs e)
{
tbxWindow.Text = miniräknare.getOperand("2", tbxWindow.Text);
}
private void btnNum3_Click(object sender, EventArgs e)
{
tbxWindow.Text = miniräknare.getOperand("3", tbxWindow.Text);
}
private void btnNum4_Click(object sender, EventArgs e)
{
tbxWindow.Text = miniräknare.getOperand("4", tbxWindow.Text);
}
private void btnNum5_Click(object sender, EventArgs e)
{
tbxWindow.Text = miniräknare.getOperand("5", tbxWindow.Text);
}
private void btnNum6_Click(object sender, EventArgs e)
{
tbxWindow.Text = miniräknare.getOperand("6", tbxWindow.Text);
}
private void btnNum7_Click(object sender, EventArgs e)
{
tbxWindow.Text = miniräknare.getOperand("7", tbxWindow.Text);
}
private void btnNum8_Click(object sender, EventArgs e)
{
tbxWindow.Text = miniräknare.getOperand("8", tbxWindow.Text);
}
private void btnNum9_Click(object sender, EventArgs e)
{
tbxWindow.Text = miniräknare.getOperand("9", tbxWindow.Text);
}
private void btnNum0_Click(object sender, EventArgs e)
{
if (tbxWindow.Text != "") tbxWindow.Text = miniräknare.getOperand("0", tbxWindow.Text);
}
private void btnOperatorDivision_Click(object sender, EventArgs e)
{
}
private void btnOperatorTimes_Click(object sender, EventArgs e)
{
}
private void btnOperatorPlus_Click(object sender, EventArgs e)
{
miniräknare.Op = "+";
}
private void btnOperatorMinus_Click(object sender, EventArgs e)
{
miniräknare.Op = "-";
miniräknare.Change = true;
}
private void btnDecimal_Click(object sender, EventArgs e)
{
tbxWindow.Text = miniräknare.getOperand(",", tbxWindow.Text);
}
private void btnClear_Click(object sender, EventArgs e)
{
}
private void btnSin_Click(object sender, EventArgs e)
{
}
private void btnCos_Click(object sender, EventArgs e)
{
}
private void btnTan_Click(object sender, EventArgs e)
{
}
private void btnSquared_Click(object sender, EventArgs e)
{
}
private void btnModulus_Click(object sender, EventArgs e)
{
}
private void btnExponential_Click(object sender, EventArgs e)
{
}
private void btnlogarithm_Click(object sender, EventArgs e)
{
}
private void btn1OverX_Click(object sender, EventArgs e)
{
}
private void btnLn_Click(object sender, EventArgs e)
{
}
private void btnPi_Click(object sender, EventArgs e)
{
}
private void btnMemoryClear_Click(object sender, EventArgs e)
{
}
private void btnMemoryRecall_Click(object sender, EventArgs e)
{
}
private void btnMemorySave_Click(object sender, EventArgs e)
{
}
}
}
My class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Miniräknare
{
class Miniräknare
{
private double first;
private double second;
private string op;
private double memory;
private bool change;
public Miniräknare(double first, double second, string op, double memory, bool change)
{
this.first = 0;
this.second = 0;
this.op = "";
this.memory = 0;
this.change = false;
}
public double First
{
get {return first; }
set { first = value; }
}
public double Second
{
get { return second; }
set { second = value; }
}
public string Op
{
get { return op; }
set { op = value; }
}
public double Memory
{
get { return memory; }
set { memory = value; }
}
public bool Change
{
get { return change; }
set { change = value; }
}
public string getOperand(string t, string textBox)
{
textBox = textBox + t;
if (t.Equals(","))
{
change = true;
second = double.Parse(textBox);
}
else if (op.Equals(""))
{
if (!change)
{
textBox = "";
change = true;
textBox = textBox + t;
}
first = double.Parse(textBox);
}
else
{
if (!change)
{
textBox = "";
change = true;
textBox = textBox + t;
}
second = double.Parse(textBox);
}
return textBox;
}
/* public string calculateAnswer()
{
} */
public string doEquals()
{
if (op == "-" ) return (first - second).ToString();
else return null;
}
}
}
In the following block after pressing "+" button "change" is true and the block is skipped when type the first digit of the second number.
else
{
if (!change)
{
textBox = "";
change = true;
textBox = textBox + t;
}
second = double.Parse(textBox);
}
since you assigned textBox at the beginning of the getOperand method, it will return the value combining what you already had on the screen with the new char.
public string getOperand(string t, string textBox)
{
textBox = textBox + t;
This should do the trick:
public string getOperand(string t, string textBox)
{
if (t.Equals(","))
{
textBox = textBox + t;
change = true;
second = double.Parse(textBox);
}
else if (Op.Equals(""))
{
textBox = textBox + t;
if (!change)
{
textBox = "";
change = true;
textBox = textBox + t;
}
first = double.Parse(textBox);
}
else
{
if (!change)
{
textBox = textBox + t;
}
else
{
textBox = t;
change = false;
}
second = double.Parse(textBox);
}
return textBox;
}
I know this is not https://codereview.stackexchange.com/ and this does not answer the question asked (which has already been answered) and might be marked as off-topic, but wanted to show the changes as suggested in the various comments in an orderly fashion, just to help you improve your coding (current and future) experience.
Changes that can be made to your Miniräknare class (Comments added to explain):
public class Miniräknare
{
public Miniräknare()
{
// Have a default constructor that sets all the default properties
First = 0;
Second = 0;
Op = "";
Memory = 0;
Change = false;
}
public Miniräknare(double first, double second, string op, double memory, bool change)
{
// If you have a constructor with parameters, use the parameters to set your properties
First = first;
Second = second;
Op = op;
Memory = memory;
Change = change;
}
// Use automatic properties, this improves readability and less confusion (As per D Stanley in comments)
public double First { get; set; }
public double Second { get; set; }
public string Op { get; set; }
public double Memory { get; set; }
public bool Change { get; set; }
public string getOperand(string t, string textBox)
{
// Apply changes as per the accepted answer
textBox = textBox + t;
if (t.Equals(","))
{
Change = true;
Second = double.Parse(textBox);
}
else if (Op.Equals(""))
{
if (!Change)
{
textBox = "";
Change = true;
textBox = textBox + t;
}
First = double.Parse(textBox);
}
else
{
if (!Change)
{
textBox = "";
Change = true;
textBox = textBox + t;
}
Second = double.Parse(textBox);
}
return textBox;
}
public string doEquals()
{
if (Op == "-") return (First - Second).ToString();
else return null;
}
}
Changes in your Form1:
Instantiate your miniräknare variable now like this, since you where setting them to the defaults with your original input parameters.
miniräknare = new Miniräknare();
Replace all your btnNum1_Click to btnNum9_Click event handlers with this single event handler to improve readability and volume of your code (Check additional comments in the code):
private void btnNumber_Click(object sender, EventArgs e)
{
// !! Remember !! to set the Tag value of each of your buttons to their corresponding values
// Then change btnNum1 to btnNum9's Click events to btnNumber_Click
// Additionally you can also just use ((Button)sender).Text if their text values will never change
// You could even do this with your operators, unless you have specific code for the button (like you have for btnNum0)
tbxWindow.Text = miniräknare.getOperand(((Button)sender).Tag as String, tbxWindow.Text);
}
can I pass EditQuestionMaster(int qid_value) this qid_value ,within this private void button1_Click(object sender, EventArgs e) button click ,if yes than how can i do this so that I can UpdateQuestion properly
public partial class EditQuestionMaster : Form
{
DbHandling db = new DbHandling();
public EditQuestionMaster(int qid_value)
{
InitializeComponent();
string subNtop = db.GetEditSubNTopic(qid_value);
string[] subNtopData = subNtop.Split('~');
cmbSubject.Text = subNtopData[2];
}
private void button1_Click(object sender, EventArgs e)
{
int qid = ; //here i want the value of int qid_value
string AnsOp = "";
if (radioButton1.Checked == true)
AnsOp = "1";
else if (radioButton2.Checked == true)
AnsOp = "2";
else if (radioButton3.Checked == true)
AnsOp = "3";
else if (radioButton4.Checked == true)
AnsOp = "4";
else
{
MessageBox.Show("Answer Option Not Selected");
return;
}
string Marks = cmbMarks.SelectedItem.ToString();
if (db.UpdateQuestion(qid, txtQuestion.Text, txtOption1.Text, txtOption2.Text, txtOption3.Text, txtOption4.Text, AnsOp, Marks, "T"))
MessageBox.Show("Question Updated Successfully");
else
MessageBox.Show("Failed to Update Question");
}
}
thanks in advance for any help
public partial class EditQuestionMaster : Form
{
DbHandling db = new DbHandling();
int qid; // here is the class variable
public EditQuestionMaster(int qid_value)
{
InitializeComponent();
this.qid = qid_value; // set the value here
string subNtop = db.GetEditSubNTopic(qid_value);
string[] subNtopData = subNtop.Split('~');
cmbSubject.Text = subNtopData[2];
}
private void button1_Click(object sender, EventArgs e)
{
qid // use it here
Expanding on chancea's answer:
You can define a business object to handle the updates like so:
public class QuestionEditor
{
DbHandling db = new DbHandling();
int questionId;
public QuestionEditor(int questionId)
{
this.questionId = questionId;
}
public void SetAnswer(string answerOption)
{
db.UpdateQuestion(qid, answerOption);
}
}
When your form is created, have it create a new instance of your business object:
public partial class EditQuestionMaster : Form
{
QuestionEditor editor;
public EditQuestionMaster(int qid_value)
{
InitializeComponent();
editor = new QuestionEditor(qid_value);
}
}
Now other methods in your form can call into the editor to perform operations.
private void button1_Click(object sender, EventArgs e)
{
string answerOption;
// switch populates answerOption
editor.SetAnswer(answerOption);
}
By moving your logic to perform updates away from the form where the user interacts is called an abstraction. This abstraction allows the UI code to evolve somewhat independently of how the question data is accessed/stored. This is the basis for n-Tier architecture.