Link to home
Start Free TrialLog in
Avatar of rwheeler23
rwheeler23Flag for United States of America

asked on

C# property cannot be assigned

Why do I get this message on line

            Properties.Settings.Default.TSServer = tsServer;

"Property or index 'TS Server' cannot be assigned to -- it is read only


namespace Time.Tracker
{
    public partial class frmLogin : Form
    {
        string tsServer;
        string tsDatabase;
        string tsUserID;
        string tsPassword;
        public frmLogin()
        {
            InitializeComponent();
        }

        public string TSServer
        {
            get { return tsServer; }
        }

        private void btnLogin_Click(object sender, EventArgs e)
        {
            tsServer   = txtServer.Text.Trim();
            tsDatabase = txtDatabase.Text.Trim();
            tsUserID   = txtUserID.Text.Trim();
            tsPassword = txtPassword.Text.Trim();

            Properties.Settings.Default.TSServer = tsServer;
        }

        private void frmLogin_Load(object sender, EventArgs e)
        {
            txtServer.Text   = Properties.Settings.Default.TSServer;
            txtDatabase.Text = Properties.Settings.Default.TSDatabase;
        }
    }
}

Avatar of AndyAinscow
AndyAinscow
Flag of Switzerland image

public string TSServer
        {
            get { return tsServer; }
            set { tsServer = value; }
        }

You are missing a 'setter' which is why it appears to be readonly
Avatar of rwheeler23

ASKER

The message remains after adding the set line.

namespace Time.Tracker
{
    public partial class frmLogin : Form
    {
        string tsServer;
        string tsDatabase;
        string tsUserID;
        string tsPassword;
        public frmLogin()
        {
            InitializeComponent();
        }

        public string TSServer
        {
            get { return tsServer; }
            set { tsServer = value; }
        }

        private void btnLogin_Click(object sender, EventArgs e)
        {
            tsServer   = txtServer.Text.Trim();
            tsDatabase = txtDatabase.Text.Trim();
            tsUserID   = txtUserID.Text.Trim();
            tsPassword = txtPassword.Text.Trim();

            Properties.Settings.Default.TSServer = tsServer;
        }

        private void frmLogin_Load(object sender, EventArgs e)
        {
            txtServer.Text   = Properties.Settings.Default.TSServer;
            txtDatabase.Text = Properties.Settings.Default.TSDatabase;
        }
    }
}
You don't actually use the setter in your class in the code you posted.

Do you mean it fails here
            Properties.Settings.Default.TSServer = tsServer;
If yes then check what Properties.Settings.Default.TSServer is
Under Project->Properties->Settings TSServer is of type string and scope is Application and the value is the name of the server. I use this technique in dozens of other applications. I cannot see what is different about this one. If you were to try to build this on your side is it successful?
ASKER CERTIFIED SOLUTION
Avatar of ste5an
ste5an
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
To add to what Andy is saying, this will fail:

Properties.Settings.Default.TSServer = tsServer;

...if TSServer is an Application-scope setting. The Application scope is read-only at runtime, while User scope can be updated.
Sorry - I got distracted for a moment while typing up my comment - wasn't trying to duplicate what ste5an had said.
Ahh.  Not read the original question closely enough as to what was failing.  
However it looks like you are having a duplicate with the same named property of your login form as one of your settings in properties.  If they really are the same information then one of them is redundant and can lead to difficult to find bugs (one gets modified and then the other is used)
What would be the best practice here? Using TSServer as an example.
In the properties section there is a property called TSServer
I then have a class called Globals that contains a global variable called TSServer
I then also use a vraiable called tsServer
The user may want to change the database name after launching the program so the properties version is there simply as a default.

What would be the clearest way to name these variables?
In your scenario, I would simply not utilize the Globals variable TSServer or the local form variable tsServer, and just make Properties.Settings.Default.TSServer a user-scope setting and use that variable for each call.

That way, if a user changes their database name or any other settings, you can call Properties.Settings.Default.Save() to save the changes locally so they persist at the next load.
This assumes the user knows how to adjust the config file. I am simply trying to make this as easy as possible. I never know who will copy the program and onto what server. Giving them the ability to change the server on the fly is what I am trying to accomplish.
I'm not sure if I follow that last comment. Are you saying you intend for users to adjust the config file? Normally, I presume a user does NOT know how to do that (even if it's technically simple). An app is more user-friendly if the user doesn't have to know about the guts.

What I was suggesting was that I presumed you would have a configuration screen somewhere in your application, where the user could put in new settings and test them. If they worked, they could click a save button in that screen.

From there, you would just update the Properties.Settings.Default.<variable name> value and then call Properties.Settings.Default.Save() after you've updated them all. The guts of that Save() call will take care of everything for you - it will save the new values to a separate user config file that's stored within your appdata folder. For the sake of being thorough, it will save it to the following path (assuming your app is called TimeTracker.exe and your app's version is 1.0.0.0):

C:\Users\Username\AppData\Local\TimeTracker\TimeTracker .exe_<some chars>\1.0.0.0\user.config

The next time the user loads up the app, it'll automatically pull in the values from user.config and use those. 
Best practice.  Naming......

My initial thoughts when planning something.
Think of 3 layers.  Each layer has a general purpose.  Data.  Business. User.
Layer 1.  Data.  This is to obtain data from permanent storage and to save data back to that storage.
Layer 2.  Business.  This queries the data layer for the individual items, assembles data into the information requested, dissembles user input and passes the info back to the data layer.  (It is not to make a simple copy of eg. a customer name.  It is the postman delivering the letters).
Layer 3.  User.  This is the user input/output level where the user requests information or inputs information.  The layer passes information to/from the business layer.

eg.  The user wants to know all the orders for a customer this year.  The user layer provides an interface to allow the user to enter the selections.  It then requests the info from the business layer.  That then requests from the data layer the info concerning the customer, the orders, the articles on the order, the monies paid/due....  The data layer then retrieves from one (or more) storages the necessary information.

Why.  Change from a file storage to a database storage - business and user layers aren't interested in where and how the data is stored.  Changes from one reporting tool to another - business and data layers don't come into that equation.  You can totally rework the GUI from a winforms to a browser based solution - business and data layers are unchanged.

For some apps this might well be overkill (or too simple).  It does however give you a start in the overall framework.
Good comments all around. I will incorporate them into future projects. Sometimes my projects connect to only 1 database, sometimes 20 or 30. I want to give the user the ability to bop around on demand. Start them off with a default database but then change when necessary. The  most likely scenario for me is one instance of SQL with one master database. These settings will be in the config file. That one master database may have several related databases. It is these databases that will selected on demand.