开发者

data binding non-strings to TextBox.Text (WinForms)

I'm storing a whole bunch of settings for my winforms program in various .settings files. Included in these settings are System.Drawing.Point, System.Drawing.Location, System.TimeSpan, System.DateTime, etc...

When I bind a form's Location to a System.Drawing.Location, and call the .Save() method, it all seems to work fine. That is, since there doesn't seem to be a need for a cast, the form's System.Drawing.Location is directly compatible with the System.Drawing.Location setting stored in the .settings file. Additionally, if I say TimeSpan tim开发者_如何学JAVAeSpan = Settings.Duration; that also works fine.

Now, I have made a large settings form, where the user can adjust various parameters, including the various DateTime and TimeSpan settings. These are visible and editable in many TextBox, which I have data bound in the following way:

Settings DefaultSettings = Settings.Default;
TextBox1.DataBindings.Add(("Text", DefaultSettings, "Duration", false, DataSourceUpdateMode.OnValidation, new TimeSpan(00, 30, 00));

The TimeSpan is visible in the TextBox, however when I try to edit it and call Save() on the settings data source, I get the following error:

Value of '0' is not valid for 'Value'. 'Value' should be between 'Minimum' and 'Maximum'. Parameter name: Value

The error originates from the Visual Studio generated code block:

[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("00:30:00")]
public global::System.TimeSpan StartWorkDay {
  get {
    return ((global::System.TimeSpan)(this["Duration"]));
  }
  set {
    this["Duration"] = value;
  }
}

I think the problem is caused by the fact that it's trying to turn a string into a System.TimeSpan, and the various other classes I have in my .settings file.

Since I'm binding them using the DataBindings.Add( which accepts strings for the parameters, I can't cast or use the new keyword there.

I could handle it all manually in code: updating the settings file by constructing the objects parameter-by-parameter, but I have so many settings stored in so many TextBoxes and NumericUpDowns that I would prefer to just bind them straight to the TextBox, assuming that's possible.

What is the easiest way I can achieve this?


You could declare a “conversion property” (I just invented that term) in the Settings class:

public class Settings
{
    // The real property
    public TimeSpan StartWorkDay { get; set; }

    // The conversion property
    public string StartWorkDayString
    {
        get
        {
            return StartWorkDay.ToString();
            // (or use .ToString("...") to format it)
        }
        set
        {
            StartWorkDay = TimeSpan.Parse(value);
            // (or use TryParse() to avoid throwing exceptions)
        }
    }
}

... and then bind the textbox to that.


I tried the following code in a sample windows form application and it did the save without any exceptions.

// Define the settings binding source
private System.Windows.Forms.BindingSource settingsBindingSource;

 private void InitializeComponent()
  {
            this.components = new System.ComponentModel.Container();
            this.durationTextBox = new System.Windows.Forms.TextBox();
            this.settingsBindingSource = new BindingSource(this.components);
            this.settingsBindingSource.DataSource = typeof(WindowsFormsApplication1.Properties.Settings);
            this.durationTextBox.DataBindings.Add(new Binding("Text", this.settingsBindingSource, "Duration", true));
  }

// In the form load event where the textbox is displayed
private void Form1_Load(object sender, System.EventArgs e)
{
   settingsBindingSource.DataSource = Settings.Default;
}

// save button click
private void button1_Click_1(object sender, System.EventArgs e)
{
   // This saved the settings, without any exceptions
   Settings.Default.Save();
}

Hope it helps.


I came up with a somewhat-elegant solution which you might be interested in:

Since the problem seemed to be that I was unable to cast or construct the data types I had in the .settings file from simple text boxes as I was using data binding, I instead made some custom controls.

For example, the TimeSpans now use a TimeSpanPicker which I made out of a DateTimePicker control, with the date disabled, the up/down toggles on, and the Value property is converted to a TimeSpan from within the picker control.

The added advantage of this method is that I don't need to do a lot of the validation I needed to before with text boxes, as the TimeSpanPicker base control DateTimePicker will only show valid times. What little validation I do need to do can be done in the Set{} property, so I don't need to define event handlers.

This seems to be working well! Now all I need to do is replace all the text boxes with custom controls.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜