C# 将非字符串绑定到TextBox.Text的数据(WinForms)

C# 将非字符串绑定到TextBox.Text的数据(WinForms),c#,winforms,data-binding,textbox,C#,Winforms,Data Binding,Textbox,我正在各种.settings文件中存储winforms程序的所有设置。 这些设置包括系统.Drawing.Point,系统.Drawing.Location,系统.TimeSpan,系统.DateTime等 当我将表单的位置绑定到系统.Drawing.Location,并调用.Save()方法时,一切似乎都很正常。也就是说,由于似乎不需要强制转换,表单的System.Drawing.Location与存储在.settings文件中的System.Drawing.Location设置直接兼容。 另

我正在各种.settings文件中存储winforms程序的所有设置。 这些设置包括
系统.Drawing.Point
系统.Drawing.Location
系统.TimeSpan
系统.DateTime

当我将表单的
位置
绑定到
系统.Drawing.Location
,并调用
.Save()
方法时,一切似乎都很正常。也就是说,由于似乎不需要强制转换,表单的
System.Drawing.Location
与存储在.settings文件中的
System.Drawing.Location
设置直接兼容。 另外,如果我说
TimeSpan TimeSpan=Settings.Duration也可以正常工作

现在,我制作了一个大型设置表单,用户可以在其中调整各种参数,包括各种
DateTime
TimeSpan
设置。它们在许多
文本框中可见且可编辑,我通过以下方式对其进行数据绑定:

Settings DefaultSettings = Settings.Default;
TextBox1.DataBindings.Add(("Text", DefaultSettings, "Duration", false, DataSourceUpdateMode.OnValidation, new TimeSpan(00, 30, 00));
TimeSpan
文本框中可见,但是当我尝试编辑它并在设置数据源上调用
Save()
时,我得到以下错误:

“0”的值对于“值”无效“值”应介于“最小值”和“最大值”之间。 参数名称:Value

错误源于Visual Studio生成的代码块:

[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;
  }
}
我认为问题是由于它试图将字符串转换为
System.TimeSpan
,以及.settings文件中的各种其他类

由于我使用接受参数字符串的
DataBindings.Add(
)绑定它们,因此我无法在那里强制转换或使用new关键字

我可以在代码中手动处理这一切:通过逐个参数构造objects参数来更新设置文件,但是我有太多的设置存储在太多的文本框和数字设置中,我宁愿直接将它们绑定到
TextBox
,假设这是可能的


实现这一点最简单的方法是什么?

您可以在
设置
类中声明一个“转换属性”(我刚刚发明了这个术语):

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)
        }
    }
}

…然后将文本框绑定到它。

您可以在
设置
类中声明一个“转换属性”(我刚刚发明了这个术语):

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)
        }
    }
}

…然后将文本框绑定到该文本框。

我在一个示例windows窗体应用程序中尝试了以下代码,它完成了保存,没有任何异常

// 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();
}

希望对您有所帮助。

我在一个示例windows窗体应用程序中尝试了以下代码,它在保存时没有任何异常

// 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();
}

希望能有所帮助。

我提出了一个稍微优雅的解决方案,您可能会感兴趣:

由于使用数据绑定时,我无法从简单的文本框中强制转换或构造.settings文件中的数据类型,因此我创建了一些自定义控件

例如,TimeSpans现在使用一个
TimeSpanPicker
,我用一个
DateTimePicker
控件制作了一个
TimeSpan选择器,在禁用日期的情况下,向上/向下切换打开,
Value
属性从选择器控件内转换为TimeSpan

此方法的另一个优点是,我不需要使用文本框执行以前需要执行的大量验证,因为TimeSpanPicker基控件DateTimePicker只显示有效时间。我需要执行的少量验证可以在Set{}属性中执行,因此我不需要定义事件处理程序

这似乎工作得很好!
现在,我需要做的就是将所有文本框替换为自定义控件。

我提出了一个优雅的解决方案,您可能会感兴趣:

由于使用数据绑定时,我无法从简单的文本框中强制转换或构造.settings文件中的数据类型,因此我创建了一些自定义控件

例如,TimeSpans现在使用一个
TimeSpanPicker
,我用一个
DateTimePicker
控件制作了一个
TimeSpan选择器,在禁用日期的情况下,向上/向下切换打开,
Value
属性从选择器控件内转换为TimeSpan

此方法的另一个优点是,我不需要使用文本框执行以前需要执行的大量验证,因为TimeSpanPicker基控件DateTimePicker只显示有效时间。我需要执行的少量验证可以在Set{}属性中执行,因此我不需要定义事件处理程序

这似乎工作得很好!
现在,我需要做的就是用自定义控件替换所有文本框。

您应该向WinForms、asp.net、WPF或您正在使用的任何技术添加标记。这个问题与c无关,而与您的演示技术有关的大部分内容。我只是编辑它以显示它是WinForms。您应该向WinForms、asp.n添加标记et、WPF或您正在使用的任何技术。这个问题与c#关系不大,大部分与您的演示技术有关。我只是编辑它以显示它是WinForms。