Public string of usercontrol not displaying anything? - c#

In my usercontrol ViewUser the groupbox header and textblock isnt displaying UserID?
Main Window:
private void btnGeneral_Click(object sender, RoutedEventArgs e)
{
ViewUser myusercontrol = new ViewUser();
String id = (String)((Button)sender).Tag;
myusercontrol.UserID = id;
PanelMainContent.Children.Add(myusercontrol);
}
private void button1_Click(object sender, RoutedEventArgs e)
{
string uriUsers = "http://localhost:8000/Service/User";
XDocument xDoc = XDocument.Load(uriUsers);
var sortedXdoc = xDoc.Descendants("User")
.OrderByDescending(x => Convert.ToDateTime(x.Element("TimeAdded").Value));
foreach (var node in xDoc.Descendants("User"))
{
Button btnFindStudent = new Button();
btnUser.Click += this.btnGeneral_Click;
btnUser.Tag = String.Format(node.Element("UserID").Value);
//also tryed btnUser.Tag = node.Element("UserID").Value;
UserControl:
public partial class ViewUser : UserControl
{
public ViewUser()
{
InitializeComponent();
}
private string _user;
public string UserID
{
get { return _userID; }
set { _userID = value; }
}
protected override void OnInitialized(EventArgs e)
{
base.OnInitialized(e);
groupBox1.Header = UserID;
textBlock1.Text = UserID;
}
}
}

Kirsty, you should update the GroupBox and TextBlock every time the UserID property changes:
public string UserID
{
get { return _userID; }
set
{
_userID = value;
groupBox1.Header = _userID;
textBlock1.Text = _userID;
}
}
Currently you're updating the GroupBox and TextBlock only a single time in OnInitialized. But OnInitialized is called only once after the ViewUser control is initialized and never again.
This is what n8wrl meant with the second part of his answer.

You're setting groupBox1.Header and textBlock1.Text before UserID is being set. Two options:
Override OnPreRender and set them in there.
or
Set them directly from your property:
public string UserID
{
get { return textBlock1.Text; }
set
{
textBlock1.Text = value;
groupBox1.Header = value;
}
}

Related

MouseClickEvent for a UserControl doesn't fire when its Children are clicked

Sorry for my query but I am just a beginner in using UserControl:
Why do MouseClickEvent of a UserControl doesn't get inherited by the controls (e.g Labels) inside it?
To show you how I instantiate the UserControl inside a flowLayoutPanel:
studentItemList[] listItem = new studentItemList[dt.Rows.Count];
for (int i = 0; i < listItem.Length; i++)
{
listItem[i] = new studentItemList();
listItem[0].Anchor = AnchorStyles.Right;
listItem[i].MouseDoubleClick += StudentPrev;
listItem[i].StudentID = dt.Rows[i].Field<string>(0);
listItem[i].StudentName = dt.Rows[i].Field<string>(1) + ", " + dt.Rows[i].Field<string>(2) + " " + dt.Rows[i].Field<string>(3);
listItem[i].StudentEmail = dt.Rows[i].Field<string>(4);
listItem[i].StudentStatus = dt.Rows[i].Field<string>(5);
flowLayoutPanelStudents.Controls.Add(listItem[i]);
}
studentItemList.cs:
public partial class studentItemList : UserControl
{
public studentItemList()
{
InitializeComponent();
}
private string _studID, _studName, _studEmail, _status;
public string StudentID
{
get { return _studID; }
set { _studID = value; studentNo.Text = value; }
}
public string StudentName
{
get { return _studName; }
set { _studName = value; studentName.Text = value; }
}
private void studentNo_Click(object sender, EventArgs e)
{
}
public string StudentEmail
{
get { return _studEmail; }
set { _studEmail = value; studentEmail.Text = value; }
}
public string StudentStatus
{
get { return _status; }
set { _status = value; status.Text = value; }
}
private void label1_Click(object sender, EventArgs e)
{
}
}
Label.Autosize is set to true and DockStyles are set to Left.
Although, the MouseEvent get's triggered when the parent Panel of the UserControl is clicked.
What's the reason behind this?
You need to wire up all controls that may receive a click event.
If all controls in yout user control are added before the control is instantiated (e.g. design-time) then you can add event handlers in the user control's constructor.
If the user control has controls added/removed at run-time then you'll need to wire up ControlAdded and ControlRemoved events to wire/unwire events.

How can I get the usercontrol to pass the values from the form it is initiated in to another one?

I am creating this simple video game ordering application. I have create an userControl named productControl. Code:
public partial class productControl : UserControl
{
private string pName;
private float pPrice;
private string pDesc;
private string pImgUrl;
public productControl() => InitializeComponent();
public string getName
{
get => pName;
set
{
pName = value;
productName.Text = pName;
}
}
public float getPrice
{
get => pPrice;
set
{
pPrice = value;
productPrice.Text = pPrice.ToString("c");
}
}
public string getDescription
{
get => pDesc;
set
{
pDesc = value;
descriptionText.Text = pDesc;
}
}
public string getImage
{
get => pImgUrl;
set
{
pImgUrl = value;
prodImage.Load(pImgUrl);
prodImage.SizeMode = PictureBoxSizeMode.StretchImage;
}
}
public int getProdId { get; set; }
private void buyButton_Click(object sender, EventArgs e)
{
MessageBox.Show(pPrice.ToString("c"));
orderConfirmation o = new orderConfirmation();
o.Show();
}
}
And a Windows Forms named accountMain. Which retrieves data from SQL and calls the productControl to fill it up.
private string productRetriever = "SELECT prodId, prodName, prodPrice, prodImg, prodDesc FROM [dbo].[products]";
private void accountMain_Load(object sender, EventArgs e)
{
createFunctions();
}
private void createFunctions()
{
connection.Open();
SqlCommand retProduct = new SqlCommand(productRetriever, connection);
panel1.Controls.Clear()
using (var reader = retProduct.ExecuteReader())
{
int count = 0;
while(reader.Read())
{
p[count] = new productControl();
p[count].Name = count.ToString();
p[count].getProdId = (int)reader[0];
p[count].getName = (string)reader[1];
p[count].getPrice = (float)reader[2];
p[count].getImage = (string)reader[3];
p[count].getDescription = (string)reader[4];
panel1.Controls.Add(p[count]);
count++;
}
}
connection.Close();
}
Above I am using a while loop to populate the panel1 with productControl inside of the accountMain Form. How can I get userControl to hide the accountForm and show another form (passing the values into the new form like title and price) when I click the "Buy" button which is inside the userControl.
Also I am new to implementing SQL into C# is it the correct way to populate the panel1 in accountMain using executeReader() or is there a better approach of retrieving data from SQL and showing it in userControl?

Custom DateTimePicker control

I have created the user control that implements DateTimePicker. But I have problems with Databindings. When Control is loaded dtp.Value has default DateTime.Now value. Why?
//Part of Form InitializeComponent() :
this.dtp_user.DataBindings.Add(new System.Windows.Forms.Binding("Value", this.employeesBindingSource, "BirthDate", true));
// Custom Control Contains two buttons and textBox (usrText)
public partial class usrDateTimePicker : UserControl
{
private DateTimePicker dtp;
private bool _cheked;
public bool Checked
{
get { return _cheked; }
set { _cheked = value; }
}
public DateTime Value
{
get { return dtp.Value; }
set
{
if (value < DateTime.MinValue && value > DateTime.MaxValue)
value = DateTime.Now;
dtp.Value = value;
}
}
public override string Text
{
get { return usrText.Text; }
}
public ControlBindingsCollection DataBindings
{
get { return dtp.DataBindings;}
}
usrCalendar clnd;
Popup _popup;
public usrDateTimePicker()
{
InitializeComponent();
InitStyles();
InitControls();
}
private void InitStyles()
{
//
}
private void InitControls()
{
dtp = new DateTimePicker();
clnd = new usrCalendar();
_popup = new Popup(clnd);
_popup.Closed += popup_Closed;
}
protected override void OnLoad(EventArgs e)
{
usrText.Text = FormatDate(dtp.Value);
base.OnLoad(e);
}
protected override void OnSizeChanged(EventArgs e)
{
//
}
private void btn_datetimepick_Click(object sender, EventArgs e)
{
if (!_popup.Visible)
{
_popup.Show(this);
}
else
_popup.Close();
}
private void popup_Closed(object sender, ToolStripDropDownClosedEventArgs e)
{
dtp.Value = clnd.Value;
usrText.Text = FormatDate(dtp.Value);
_cheked = true;
if (usrText.Text == string.Empty || usrText.Text == "")
_cheked = false;
}
private string FormatDate(DateTime date)
{
//
}
By default the Value of DatePicker control is set to DateTime.Now unless you set a value specifically. Read Here

C# Custom Class using INotifyPropertyChanged not notifying on Assignment

I have a class that implements the INotifyPropertyChanged interface.
If I create a new instance of the object, the PropertyChanged event gets set after I retrieve a value from it.
Example:
MyItem itm = new MyItem(); //MyItem.PropertyChanged == null
string test = itm.Value; //MyItem.PropertyChanged != null
If I assign itm the value of another MyItem, the PropertyChanged event remains null.
Example:
itm = (MyItem)cboMyItemsCombobox.SelectedItem; // Properties for itm change to the values
// of the selected item, but PropertyChanged
// == null
I believe the problem lies partially in my custom constructor for the class, but I'm not entirely sure.
The goal is to have a variable to hold data for a record, called mnuitm, that is bound to
3 textbox objects. When the text in a textbox changes, the change is made to the property in mnuitm. When the property in mnuitm is changed, the change is made in the textbox.
This works if I create a new MenuItem and assign the values individually, but does not work if I assign an already populated MenuItem to mnuitm.
Here is my actual code for (hopefully) more clearity on the issue.
public partial class frmMenuItems : Form
{
private class MenuItem : INotifyPropertyChanged
{
private Int32 mid;
private string txt;
private string url;
private string scp;
public MenuItem() { }
public MenuItem(Int32 id, string txt, string url, string scp)
{
ID = id;
Text = txt;
URL = url;
Script = scp;
}
public Int32 ID
{
get
{
return mid;
}
set
{
if (mid != value)
{
mid = value;
NotifyPropertyChanged("ID");
}
}
}
public string Text {
get
{
return txt;
}
set
{
if (txt != value)
{
txt = value;
NotifyPropertyChanged("Text");
}
}
}
public string URL {
get
{
return url;
}
set
{
if (url != value)
{
url = value;
NotifyPropertyChanged("URL");
}
}
}
public string Script {
get
{
return scp;
}
set
{
if (scp != value)
{
scp = value;
NotifyPropertyChanged("Script");
}
}
}
public void Clear()
{
ID = 0;
Text = "";
URL = "";
Script = "";
}
public override string ToString()
{
return Text;
}
private void NotifyPropertyChanged(string inf)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(inf));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
private MenuItem mnuitm;
private MySqlConnection sqlcon;
public frmMenuItems()
{
InitializeComponent();
}
private void btnClose_Click(object sender, EventArgs e)
{
this.Close();
}
private void btnCancel_Click(object sender, EventArgs e)
{
mnuitm.Clear();
}
private void frmMenuItems_Load(object sender, EventArgs e)
{
string constr = "server={0};uid={1};pwd={2};database={3};";
DBItem dbi = CountyDataManager.CountyData.DBConnection;
constr = string.Format(constr, [MyHost], [MyUsername], [MyPassword], [MyDatabase]);
sqlcon = new MySqlConnection(constr);
sqlcon.Open();
mnuitm = new MenuItem();
SetBindings();
RefreshList();
}
private void SetBindings()
{
txtMenuText.DataBindings.Clear();
txtURL.DataBindings.Clear();
txtScript.DataBindings.Clear();
txtMenuText.DataBindings.Add("Text", mnuitm, "Text");
txtURL.DataBindings.Add("Text", mnuitm, "URL");
txtScript.DataBindings.Add("Text", mnuitm, "Script");
}
private void RefreshList()
{
using (MySqlCommand cmd = new MySqlCommand("SELECT `menuid`,`menutext`,`url`,`script` FROM tblindexmenu ORDER BY `menutext`", sqlcon))
{
lstMenuItems.Items.Clear();
using (MySqlDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
lstMenuItems.Items.Add(new MenuItem(Int32.Parse(rdr[0].ToString()), rdr[1].ToString(),rdr[2].ToString(),rdr[3].ToString()));
}
}
}
}
private void frmMenuItems_FormClosing(object sender, FormClosingEventArgs e)
{
sqlcon.Close();
}
private void lstMenuItems_SelectedIndexChanged(object sender, EventArgs e)
{
if (lstMenuItems.SelectedIndex > -1)
{
mnuitm = (MenuItem)lstMenuItems.SelectedItem;
}
}
}
After receiving feedback, I made the following changes:
Added CopyFrom() to MenuItem
public void CopyFrom(MenuItem itm)
{
this.ID = itm.ID;
this.URL = itm.URL;
this.Text = itm.Text;
this.Script = itm.Script;
}
I then modified the SelectedIndexChanged code to use the new function
mnuitm.CopyFrom((MenuItem)lstMenuItems.SelectedItem);
This is by design. When you write
itm = (MyItem)cboMyItemsCombobox.SelectedItem;
you haven't changed any of the properties of the MenuItem itm used to point to, rather you changed the MenuItem itm points to.
One option for what you need is add a function to MenuItem that looks like
SetFromOtherMenuItem(MenuItem other)
{
this.Url = other.Url
//etc
}
Again, PropertyChanged means that a property on some instance has changed. In your case, only one of the variables pointing to that instance changed (to point to a different instance).

.NET Propertygrid refresh trouble

Property grid do not show new value of selected object.
For example:
o.val = "1";
pg.SelectedObject = o;
o.val = "2";
pg.Refresh();
The property in property grid is still "1";
It is changing only if you click on this property.
Or like that:
o.val = "1";
pg.SelectedObject = o;
o.val = "2";
pg.SelectedObject = o;
but in this case focus will be changed to PropertyGrid.
As I told you in my comment, your code is not enough to understand your issue. Presented like this it should work. Here is mine that works well:
public class Target
{
private int _myInt = 1;
public int MyInt { set; get; }
public static Target target = new Target();
}
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Button button = new Button()
{
Text = "Click me",
Dock = DockStyle.Bottom
};
Form form = new Form
{
Controls = {
new PropertyGrid {
SelectedObject = Target.target,
Dock = DockStyle.Fill,
},
button
}
};
button.Click += new EventHandler(button_Click);
Application.Run(form);
}
static void button_Click(object sender, EventArgs e)
{
Target.target.MyInt = 2;
Form form = Form.ActiveForm;
(form.Controls[0] as PropertyGrid).Refresh();
}
}
The call to Refresh() actually rebuilds the grid. Remove it and you will see the change only when you click the property.
Cause you just not gave some code, here is a working example.
Just put a Button and a PropertyGrid onto a form.
using System;
using System.ComponentModel;
using System.Windows.Forms;
namespace WindowsFormsApplication
{
public partial class FormMain : Form
{
Random rand;
MyObject obj;
public FormMain()
{
InitializeComponent();
rand = new Random();
obj = new MyObject();
propertyGrid1.SelectedObject = obj;
}
private void button1_Click(object sender, EventArgs e)
{
obj.MyValue = rand.Next();
obj.IsEnabled = !obj.IsEnabled;
obj.MyText = DateTime.Now.ToString();
propertyGrid1.Refresh();
}
}
public class MyObject : INotifyPropertyChanged
{
private int _MyValue;
public int MyValue
{
get
{
return _MyValue;
}
set
{
_MyValue = value;
NotifyPropertyChanged("MyValue");
}
}
private string _MyText;
public string MyText
{
get
{
return _MyText;
}
set
{
_MyText = value;
NotifyPropertyChanged("MyText");
}
}
private bool _IsEnabled;
public bool IsEnabled
{
get
{
return _IsEnabled;
}
set
{
_IsEnabled = value;
NotifyPropertyChanged("IsEnabled");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
}
}

Categories

Resources