List Box with BindingSource containing objects not showing displayName C# - c#

I have found many answered questions on here explaining how to do this when the objects are created as part of the data source but my list box is just displaying "SharePointXMLBuilder.Farm" (Namespace.class) and not the selected DisplayName?
I dont know what I am doing wrong can anyone help please.
I have a list box with a data source as a databinding control and I am adding my created objects(Farm) to the databinding(farmListBindingSource) which all works fine, I just cant get the list to show the property I want it to.
Form: (loads another form takes input and returns to create object from Farm class)
private void CreateNewFarm_Click(object sender, EventArgs e)
{
FarmInput input = new FarmInput();
input.ShowDialog();
Farm nFarm = new Farm();
nFarm.location = input.inputLocation.ToString();
nFarm.identifier = input.inputType.ToString();
nFarm.environment = input.inputEnvironment.ToString();
this.farmListBindingSource.Add(nFarm);
this.testReturnTextBox.Text = nFarm.friendlyName;
}
private void MainForm_Load(object sender, EventArgs e)
{
this.FarmListBox.DisplayMember = "friendlyName";
this.testReturnTextBox.Text = "Form Loaded....";
}
Class:
namespace SharePointXMLBuilder
{
class Farm
{
private string farmLocation;
private string farmIdentifier;
private string farmEnvironment;
private string farmFriendlyName;
//private List<Server> farmServers;
//properties
public string friendlyName
{
get { return farmFriendlyName; }
set { farmFriendlyName = value; }
}
public string location
{
get { return farmLocation;}
set { farmLocation = value; this.buildFriendlyName(); }
}
public string identifier
{
get { return farmIdentifier; }
set { farmIdentifier = value; this.buildFriendlyName(); }
}
public string environment
{
get { return farmEnvironment; }
set { farmEnvironment = value; this.buildFriendlyName(); }
}
//constructor
public Farm()
{
}
//methods
public void AddServer(string s)
{
Server nServer = new Server(s);
// farmServers.Add(nServer);
}
public void buildFriendlyName()
{
this.friendlyName = this.location + " " + this.identifier + " " + this.environment;
}
}
}

Maybe you are not calling this function: buildFriendlyName() for each object in the list prior to binding?

In your buildfriendlyname() method set your private string farmFriendlyName insted of setting the property value friendlyname

Ok, so I tried to manually add DisplayMember in the designer and it wouldn't hold the value, as soon as I removed the DataSource it allowed DisplayMember to be populated so I changed the CreateNewFarm_Click to add the object to farmListBox.Items and when I re-ran the code it was fine.
It appears that you cannot use DisplayMember if you are pulling the objects from a DataSource.

Related

C# XML. Get data from XML to object, update in UI, save back to XML

let me describe the situation. Winforms C#
I have xml file with data. I load this data to an user defined class object using Deserialize.
Based on this object with data, I build [in Form] UI: many tabPages of custom controls (textBox, 2 buttons in groupBox). I can also save this user defined class object using Serialize to XML file.
Question:
When I update textBox.Text in Form UI in custom control I do not know how to keep connection with the object with data (Layout layout) and save the updated object with data to XML. The change of text happens only in user custom control TextBox. I want to update data from UI in data object (layout) and then simply save with Serialization.
user class:
public class Layout
{
public string type;
public List<TabPage> TabPageList;
public Layout()
{
this.TabPageList = new List<TabPage>();
}
}
public class TabPage
{
public string text;
public List<ActionGroup> ActionGroupList;
public TabPage()
{
this.ActionGroupList = new List<ActionGroup>();
}
}
public class ActionGroup
{
public string type;
public string text;
public string sourceLocal;
public string sourceRemote;
public ActionGroup()
{
this.type = string.Empty;
this.text = string.Empty;
this.sourceLocal = string.Empty;
this.sourceRemote = string.Empty;
}
}
Custom control:
public partial class ViewActionGroup : UserControl
{
public string type;
public string text;
public string sourceLocal;
public string sourceRemote;
public bool isRemote;
public bool isDone;
public ViewActionGroup()
{
this.type = string.Empty;
this.text = string.Empty;
this.sourceLocal = string.Empty;
this.sourceRemote = string.Empty;
this.isRemote = false;
this.isDone = false;
InitializeComponent();
}
public ViewActionGroup(ActionGroup actionGroup)
{
this.type = actionGroup.type;
this.text = actionGroup.text;
this.sourceLocal = actionGroup.sourceLocal;
this.sourceRemote = actionGroup.sourceRemote;
this.isRemote = false;
this.isDone = false;
InitializeComponent();
groupBox1.Text = text;
button1.Text = type;
button1.Click += new EventHandler(Button_Click);
textBox1.Text = sourceLocal;
textBox1.TextChanged += new EventHandler(textBox1_TextChanged);
}
public void ChangeToRemote()
{
isRemote = true;
textBox1.Text = this.sourceRemote;
}
public void ChangeToLocal()
{
isRemote = false;
textBox1.Text = this.sourceLocal;
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
if (this.isRemote)
{
this.sourceRemote = textBox1.Text;
}
else
{
this.sourceLocal = textBox1.Text;
}
}
Creating UI where I loose connection between UI and data object:
private void CreateLayout(Layout layout)
{
this.Text = layout.type;
TabControl tabControl = new TabControl();
tabControl.Dock = DockStyle.Fill;
int tabCount = 0;
foreach (TabPage tabpage in layout.TabPageList)
{
int actionCount = 0;
tabControl.TabPages.Add(tabpage.text);
foreach (ActionGroup actionGroup in tabpage.ActionGroupList)
{
ViewActionGroup view = new ViewActionGroup(actionGroup);
view.Location = new Point(0, actionCount * view.Height);
tabControl.TabPages[tabCount].Controls.Add(view);
tabControl.TabPages[tabCount].AutoScroll = true;
tabControl.TabPages[tabCount].AutoScrollMinSize = new System.Drawing.Size(tabControl.Width/2,tabControl.Height);
actionCount++;
}
tabCount++;
this.panelMain.Controls.Add(tabControl);
}
}
There are two common ways:
One is a routine WriteDataIntoControls and another ReadDataFromControls where you transfer the data to and from your visible controls manually (advantage: highest degree of control). In this case you'd have to read your object from your XML source, deserialize it into your business object and create all visible controls together with their value. On saving you'd have to transfer all values into your business object and serizalize it after this.
The second is DataBinding (advantage: highest degree of automation). Read here: https://msdn.microsoft.com/en-us/library/ef2xyb33%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396
You can bind to simple values as well as to lists (including navigation) or complex objects.
You find a tutorial here: http://www.codeproject.com/Articles/24656/A-Detailed-Data-Binding-Tutorial
#Shnugo Thank You for your feedback. The tutorial you posted did not help because it is too hard for me but Data Binding topic gave me some clue.
Here easy tutorial in VB actually but simple. It helped me to do it quickly in C#.
https://www.youtube.com/watch?v=jqLQ2K9YY2A
C# solution
class MyObject
{
string name;
public MyObject()
{ }
public string Name
{
get { return name;}
set { name = value; }
}
}
public partial class Form1 : Form
{
MyObject obj = new MyObject();
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
obj.Name = "Lucas";
textBox1.DataBindings.Add("Text", obj, "Name", true, DataSourceUpdateMode.OnPropertyChanged);
}
private void button1_Click(object sender, EventArgs e)
{
label1.Text = obj.Name;
}
}

NavigateTo() Function is being called before constructor?

I am developing a Windows phone App and in my MainPage.xaml.cs file I have one private member that is being changed in the overrided method OnNavigateTo(). Although its value is changed, after that in the MainPage constructor its value resets to 0 (It's an int member). I guess that OnNavigateTo() method is being called BEFORE the constructor but if so I would have a nullReferenceException. What can cause that problem?
The OnNavigateTo() Function:
if (NavigationContext.QueryString.ContainsKey("leftDuration"))
{
//Get the selected value from IntroductionPage as a string
var leftRecievedInformation = NavigationContext.QueryString["leftDuration"];
//Convert the string to an enum object
var firstRunLeftChosenDuration = (LensLifetime)Enum.Parse(typeof(LensLifetime), leftRecievedInformation);
//Set the leftDuration value to the model object
_firstRunLeftDuration = getDurationAsNumber(firstRunLeftChosenDuration);
MessageBox.Show(_firstRunLeftDuration + "");
model.Left.LifeTime = _firstRunLeftDuration;
}
My problematic member is the _firstRunLeftDuration value. Although, as you can see, i set the model.Left.LifeTime value, in the MainPage.xaml I still get the default 0 value... It' like completely ignoring this line of code.. I know the code is not particularly clear but I don't think its beneficial to add extra lines of useless code.
Here's the MainPage.xaml.cs file:
public partial class MainPage : PhoneApplicationPage
{
public ContactLensesModel model;
private int _firstRunLeftDuration, _firstRunRightDuration; //Members used for the initialization of the app
public int FirstRunLeftDuration
{
get
{
return _firstRunLeftDuration;
}
set
{
_firstRunLeftDuration = value;
}
}
public int FirstRunRightDuration
{
get
{
return _firstRunRightDuration;
}
set
{
_firstRunRightDuration = value;
}
}
public ContactLensesModel Model
{
get
{
return model;
}
set
{
model = value;
}
}
// Constructor
public MainPage()
{
InitializeComponent();
// Sample code to localize the ApplicationBar
BuildLocalizedApplicationBar();
//Should check if the user starts the app for the first time....
//Create a new model
Model = new ContactLensesModel();
Model.setLeftNewStartingDate();
Model.setRightNewStartingDate();
//Should load the already saved model if the user in not entering for the first time...
//....
//....
loadModel();
//Connect the data Context
leftLensDaysRemaining.DataContext = Model.Left;
rightLensDaysRemaining.DataContext = Model.Right;
}
private int getDurationAsNumber(LensLifetime duration)
{
if (duration.Equals(LensLifetime.Day))
return 1;
else if (duration.Equals(LensLifetime.Two_Weeks))
return 14;
else
return DateTime.DaysInMonth(DateTime.Now.Year, DateTime.Now.Month);
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
//Get the arguments as strings and convert them to an enum, is true only when the user enters app for the first time.
if (NavigationContext.QueryString.ContainsKey("leftDuration"))
{
//Get the selected value from IntroductionPage as a string
var leftRecievedInformation = NavigationContext.QueryString["leftDuration"];
//Convert the string to an enum object
var firstRunLeftChosenDuration = (LensLifetime)Enum.Parse(typeof(LensLifetime), leftRecievedInformation);
//Set the leftDuration value to the model object
FirstRunLeftDuration = getDurationAsNumber(firstRunLeftChosenDuration);
Model.Left.LifeTime = FirstRunLeftDuration;
}
if (NavigationContext.QueryString.ContainsKey("rightDuration"))
{
//Get the selected value from IntroductionPage as a string
var rightRecievedInformation = NavigationContext.QueryString["rightDuration"];
//Convert the string to an enum object
var firstRunRightChosenDuration = (LensLifetime)Enum.Parse(typeof(LensLifetime), rightRecievedInformation);
//Set the leftDuration value to the model object
_firstRunRightDuration = getDurationAsNumber(firstRunRightChosenDuration);
Model.Right.LifeTime = _firstRunRightDuration;
}
}
/// <summary>
/// Loads the model from the isolated Storage
/// </summary>
private void loadModel()
{
//Load the model...
}
private void BuildLocalizedApplicationBar()
{
// Set the page's ApplicationBar to a new instance of ApplicationBar.
ApplicationBar = new ApplicationBar();
// Create a new button and set the text value to the localized string from AppResources.
ApplicationBarIconButton appBarSettingsButton = new ApplicationBarIconButton(new Uri("/Assets/Icons/settingsIcon4.png", UriKind.Relative));
appBarSettingsButton.Text = AppResources.AppBarSettingsButtonText;
appBarSettingsButton.Click += appBarButton_Click;
ApplicationBar.Buttons.Add(appBarSettingsButton);
// Create a new menu item with the localized string from AppResources.
//ApplicationBarMenuItem appBarMenuItem = new ApplicationBarMenuItem(AppResources.AppBarMenuItemText);
//ApplicationBar.MenuItems.Add(appBarMenuItem);
}
void appBarButton_Click(object sender, EventArgs e)
{
NavigationService.Navigate(new Uri("/SettingsPage.xaml", UriKind.RelativeOrAbsolute));
}
private void leftButtonChange_Click(object sender, RoutedEventArgs e)
{
model.setLeftNewStartingDate();
}
private void rightChangeButton_Click(object sender, RoutedEventArgs e)
{
model.setRightNewStartingDate();
}
}
}
The OnNavigatedTo method cannot be called before the constructor. The constructor is always executed first. I think your model.Left.LifeTime doesn't raise a PropertyChanged event. Hence, your View won't know you are giving it a value. Therefore it will show the default value of model.Left.Lifetime which is probably 0.
On the other hand, it's hard to tell without seeing the rest of your code.

Want to avoid default zero value

I have the a class in my application. It has been bound to winform textbox controls. But the textbox which is bound to BookingNo property, always shows zero (0). But i want the textbox keep empty. Is there any way to do it? Here is my code snippet.
public class Booking
{
private int pBookingNo;
private string pCustomerName;
private string pAddress;
public int BookingNo
{
get { return pBookingNo; }
set
{
if (!value.Equals(pBookingNo))
{
pBookingNo = value;
}
}
}
public string CustomerName
{
get { return pCustomerName; }
set
{
if (!value.Equals(pCustomerName))
{
pCustomerName = value;
}
}
}
public Booking() { }
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
AddDataBindings();
}
private void AddDataBindings()
{
bsBooking.DataSource = typeof(Booking);
txtBookingNo.DataBindings.Add("Text", bsBooking, "BookingNo", true, DataSourceUpdateMode.OnPropertyChanged, null, "G", GlobalVariables.CurrentCultureInfo);
txtCustomerName.DataBindings.Add("Text", bsBooking, "CustomerName");
}
}
The default value of an Integer is 0, so you have to wrap it into some other object, which supports values other than 0, like
public int? BookingNo { get; set; }
You can use Nullable Type
public int? pBookingNo
{
get;
set;
}
Link : http://msdn.microsoft.com/fr-fr/library/1t3y8s4s(v=vs.80).aspx
You could use custom formatting for the binding by adding a handler to the Format event (http://msdn.microsoft.com/en-us/library/system.windows.forms.binding.format.aspx) and return an empty string when the value is zero. But you wouldn't be able to tell whether the value is actually zero or it just hasn't been set already, in which case using the int? approach suggested by #Grumbler85 is better.
what´s about:
textBox1.BindingContextChanged += new EventHandler(BindingContext_Changed);
private void BindingContext_Changed(object sender, EventArgs e)
{
TextBox txtBox = (TextBox)sender;
if (txtBox.Text == "0"){
txtBox.Text = "";
}
}
don´t know if it works, just an idea.

Passing Properties Between Winforms When Using Singleton

Ok so I am trying to pass a boolean from my Login form to my Home form, normally this would be fine for me and I would just use a property. However I thought I could use a similar method this time but I am implementing the singleton factory on the forms.
Here is the Login code relevant to this:
The AdminAccess property gets set fine and I have checked the value is correct.
private bool adminAccess;
public bool AdminAccess
{
get { return adminAccess; }
private set { adminAccess = value; }
}
private void btnLogin_Click(object sender, EventArgs e)
{
//Some Code Does Stuff
OpenHome();
}
private void OpenHome()
{
HomeForm CreateHomeForm = HomeForm.HomeUI;
CreateHomeForm.StartupHome = this;
//Trying to set the property.
CreateHomeForm.AdminPermissions= this.AdminAccess;
CreateHomeForm.Show();
this.Hide();
}
Here is the relevant code from the Home form:
public HomeForm()
{
InitializeComponent();
//just to check what is in the property quickly
textBox1.Text = AdminPermissions.ToString();
}
private bool adminPermissions;
public bool AdminPermissions
{
private get { return adminPermissions; }
set { adminPermissions = value; }
}
public Form StartupHome
{
set;
get;
}
private static HomeForm homeUI;
public static HomeForm HomeUI
{
get
{
if (homeUI == null || homeUI.IsDisposed)
{
homeUI = new HomeForm();
}
return homeUI;
}
}
The value gets reset when the HomeUI if loop runs as a new instance of the form is created. I can't seem to think how to modify this to get a working solution. As you can tell I am fairly amateur so I'm just looking for a quick and clean solution to this :)
Thank you very much for your time in advance!
You assign the value in the constructor, BEFORE the AdminPermissions property is actually set. Change your code like this
public class HomeForm
{
public HomeForm()
{
InitializeComponent();
}
private bool adminPermissions;
public bool AdminPermissions
{
get { return adminPermissions; }
set {
adminPermissions = value;
textBox1.Text = value.ToString();
}
}
...
}
Try setting the textBox1.Text value in one of the Form events. Try Loaded first, then Activated. You're resetting it to false every time in your constructor!

Formating DataGridView Columns for an unbound data source

I am struggling with the WinForms DataGridView. I have a class, that I use as element to be displayed:
public class BorderFlowHistoryElement
{
public string nodeTitles { get; set; }
public double borderFlowRatio { get; set; }
...
}
I created a list of these elements:
List<BorderFlowHistoryElement> clusterHistory
which contains a list of thise elements, that should be displayed in my DataGridView. I bound the list at the DataSource of the Grid:
dataGridViewCluster.DataSource = clusterHistory;
Now the DataGridView displays the list. Now I want to format the columns which display the double values to display 5 digits. I tried it with:
dataGridViewCluster.Columns[1].DefaultCellStyle.Format = "n5";
but this has no effect on the column. Anyone knows, how I can do it right?
Additionally, I want to size the columnwidth to optimal fit for the largest entry.
Thanks in advance,
Frank
I have replicated what you have done and I had no issue whatsoever. Have you validated your data to ensure that you can actually get the results that you want?
Here is what I did just for your reference:
private void button1_Click(object sender, EventArgs e)
{
IList<BorderFlowHistoryElement> clusterHistory = FillClusterHistory();
dataGridView1.DataSource = clusterHistory;
dataGridView1.Columns[1].DefaultCellStyle.Format = "n5";
dataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);
}
private static IList<BorderFlowHistoryElement> FillClusterHistory()
{
IList<BorderFlowHistoryElement> clusterHistory = new List<BorderFlowHistoryElement>();
for(int i = 5000; i < 5020; i++)
{
BorderFlowHistoryElement element = new BorderFlowHistoryElement();
element.nodeTitles = Guid.NewGuid().ToString();
element.borderFlowRatio = i * 3.3.1415672467234823499821D;
clusterHistory.Add(element);
}
return clusterHistory;
}
}
public class BorderFlowHistoryElement
{
private string _NodeTitles;
private double _BorderFlowRatio;
public string nodeTitles
{
get { return _NodeTitles; }
set { _NodeTitles = value;}
}
public double borderFlowRatio
{
get { return _BorderFlowRatio; }
set { _BorderFlowRatio = value;}
}
}
I hope that helps in some fashion. As you can see you can do the auto sizing as well.

Categories

Resources