winforms 我试图创建我自己的助手类来保存和加载设置,但是加载部分的列表是空的,为什么列表是空的?

0wi1tuuw  于 2023-11-21  发布在  其他
关注(0)|答案(2)|浏览(133)

我知道有点长但都是有联系的。
在form1 top中,我创建了这个类:

  1. public class SettingControlPair
  2. {
  3. public string Key { get; set; }
  4. public object Value { get; set; }
  5. public Control Control { get; set; }
  6. }

字符串
然后为configurationhelper类创建了这个列表变量和一个变量:

  1. private List<SettingControlPair> settingControlPairs = new List<SettingControlPair>();
  2. private ConfigurationHelper configurationHelper;


在form1构造函数中,我初始化了configurationhelper并调用了configurationLoading方法:

  1. public Form1()
  2. {
  3. InitializeComponent();
  4. // Initialize your module classes here
  5. selectedImagePath = string.Empty;
  6. imageProcessor = new ImageProcessor(selectedImagePath);
  7. fileHandler = new FileHandler();
  8. configurationHelper = new ConfigurationHelper(settingControlPairs);
  9. if (textBoxLensSize.Text == string.Empty)
  10. {
  11. LensCropRectWidth = 10;
  12. }
  13. InitializeUI();
  14. configurationHelper.LoadConfiguration();
  15. }


我如何使用它来保存的示例:

  1. private void textBoxLensSize_TextChanged(object sender, EventArgs e)
  2. {
  3. // Perform real-time input validation
  4. if (int.TryParse(textBoxLensSize.Text, out int width))
  5. {
  6. // Valid integer input
  7. if (width >= 10)
  8. {
  9. LensCropRectWidth = width; // Update the property
  10. labelCroppedImagesCount.Focus();
  11. configurationHelper.SaveConfiguration("LensSize", width, textBoxLensSize);
  12. }
  13. else
  14. {
  15. // Show a message if the value is less than 10
  16. MessageBox.Show("Please enter a value greater than or equal to 10.");
  17. textBoxLensSize.Text = 10.ToString(); // Revert to the previous value
  18. labelCroppedImagesCount.Focus();
  19. }
  20. }
  21. }


这是储蓄线:

  1. configurationHelper.SaveConfiguration("LensSize", width, textBoxLensSize);


最后是ExclusionHelper类代码:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Windows.Forms;
  4. using static Images_Cropping.Form1;
  5. namespace Images_Cropping
  6. {
  7. public class ConfigurationHelper
  8. {
  9. private List<SettingControlPair> settingControlPairs;
  10. public ConfigurationHelper(List<SettingControlPair> settingControlPairs)
  11. {
  12. this.settingControlPairs = settingControlPairs;
  13. }
  14. public void LoadConfiguration()
  15. {
  16. foreach (var pair in settingControlPairs)
  17. {
  18. var value = Properties.Settings.Default[pair.Key];
  19. if (value != null)
  20. {
  21. pair.Value = value;
  22. if (pair.Control is TextBox textBox)
  23. {
  24. textBox.Text = value.ToString();
  25. }
  26. else if (pair.Control is CheckBox checkBox)
  27. {
  28. if (bool.TryParse(value.ToString(), out bool isChecked))
  29. {
  30. checkBox.Checked = isChecked;
  31. }
  32. }
  33. else if (pair.Control is NumericUpDown numericUpDown)
  34. {
  35. if (decimal.TryParse(value.ToString(), out decimal numericValue))
  36. {
  37. numericUpDown.Value = numericValue;
  38. }
  39. }
  40. else if (pair.Control is ComboBox comboBox)
  41. {
  42. comboBox.SelectedItem = value;
  43. }
  44. else if (pair.Control is TrackBar trackBar)
  45. {
  46. if (int.TryParse(value.ToString(), out int trackBarValue))
  47. {
  48. trackBar.Value = trackBarValue;
  49. }
  50. }
  51. }
  52. }
  53. }
  54. public bool SaveConfiguration(string key, object value, Control control)
  55. {
  56. try
  57. {
  58. // Save the configuration setting
  59. Properties.Settings.Default[key] = value;
  60. // Add the key, object value, and control to the list
  61. settingControlPairs.Add(new SettingControlPair
  62. {
  63. Key = key,
  64. Value = value,
  65. Control = control
  66. });
  67. Properties.Settings.Default.Save();
  68. return true; // Save operation succeeded
  69. }
  70. catch (Exception ex)
  71. {
  72. // Handle any exceptions related to saving the configuration
  73. Console.WriteLine("Error saving configuration: " + ex.Message);
  74. return false; // Save operation failed
  75. }
  76. }
  77. }
  78. }


问题是List settingControlPairs是空的。然后当试图在LoadConfiguration方法中循环列表时,ir什么也不做,因为List是空的。
列表为空的原因是因为我用列表初始化了form1构造函数中的configurationHelper,但列表为空:

  1. configurationHelper = new ConfigurationHelper(settingControlPairs);


列表settingControlPairs为空,因此在LoadingConfiguration方法中也为空。
我怎样才能解决这个逻辑问题,列表不会是空的?

pobjuy32

pobjuy321#

当从配置中读取字符串时,它可能只是空的而不是null。因此,为了解决这个问题,在if块(位于load方法的foreach循环中)中进行以下检查之一应该会有所帮助:

  1. if(!string.IsNullOrEmpty(value))

字符串
或者,您可以使用:用途:

  1. if(value?.Length > 0)


例如:

  1. public void LoadConfiguration()
  2. {
  3. foreach (var pair in settingControlPairs)
  4. {
  5. var value = Properties.Settings.Default[pair.Key];
  6. if (value?.Length > 0)
  7. {
  8. pair.Value = value;
  9. if (pair.Control is TextBox textBox)
  10. {
  11. textBox.Text = value.ToString()
  12. [...]

展开查看全部
k5ifujac

k5ifujac2#

查看您的代码,可以解释此行为的一件事是,在InitializeComponent中,如果在设置控件的 initial 值之前订阅了像TextBox.TextChanged这样的事件,因为这些初始(空白)值可能会保存到配置中,然后当您加载配置时,您将什么也得不到。
因此,例如,如果您有一个包含这些控件的表单,并希望在下次应用程序启动时使用相同的值填充它,那么您可以使用一种方法来解决您遇到的所有问题。


的数据
我认为你写一个JSON文件的想法(到用户的AppData文件夹)是一个很好的想法。为了安全起见,试着按照这个顺序做:

  1. public partial class MainForm : Form
  2. {
  3. string configPath { get; } =
  4. Path.Combine(
  5. Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
  6. Assembly.GetEntryAssembly().GetName().Name,
  7. "config.json"
  8. );
  9. public MainForm()
  10. {
  11. InitializeComponent();
  12. // Restore values BEFORE subscribing to events
  13. LoadConfiguration();
  14. // NOW you can safely subscribe.
  15. SubscribeToEvents();
  16. }
  17. Dictionary<string, object> ConfigurationHelper { get; set; }
  18. .
  19. .
  20. .
  21. }

字符串

从Json文件加载配置

  1. private void LoadConfiguration()
  2. {
  3. if (File.Exists(configPath))
  4. {
  5. ConfigurationHelper =
  6. JsonConvert
  7. .DeserializeObject<Dictionary<string, object>>(File.ReadAllText(configPath));
  8. foreach (var key in ConfigurationHelper.Keys)
  9. {
  10. if (Controls[key] is Control control)
  11. {
  12. if (control is TextBox textBox)
  13. {
  14. if (ConfigurationHelper.TryGetValue(key, out var value))
  15. {
  16. textBox.Text = value.ToString();
  17. }
  18. }
  19. else if (control is NumericUpDown numeric)
  20. {
  21. if (ConfigurationHelper.TryGetValue(key, out var o) && int.TryParse($"{o}", out int value))
  22. {
  23. numeric.Value = value;
  24. }
  25. }
  26. else if (control is ComboBox comboBox)
  27. {
  28. if (ConfigurationHelper.TryGetValue(key, out var o) && int.TryParse($"{o}", out int value))
  29. {
  30. comboBox.SelectedIndex = value;
  31. }
  32. }
  33. else if (control is TrackBar trackBar)
  34. {
  35. if (ConfigurationHelper.TryGetValue(key, out var o) && int.TryParse($"{o}", out int value))
  36. {
  37. trackBar.Value = value;
  38. }
  39. }
  40. else if (control is CheckBox checkBox)
  41. {
  42. if (ConfigurationHelper.TryGetValue(key, out var o) && bool.TryParse($"{o}", out bool value))
  43. {
  44. checkBox.Checked = value;
  45. }
  46. }
  47. }
  48. }
  49. }
  50. else
  51. {
  52. Directory.CreateDirectory(Path.GetDirectoryName(configPath));
  53. ConfigurationHelper = new Dictionary<string, object>();
  54. }
  55. }

订阅更改事件

确保浏览Designer.cs文件。要么完全删除TextChangedSelectionIndexChanged等控制更改事件的现有处理程序,* 或者 * 至少浏览这些处理程序,确保它们不会对配置文件进行任何写入。这些处理程序有真实的可能导致竞争条件,从而导致您看到的问题。* 需要明确的是,将一个事件多次订阅到多个处理程序是完全可以的。如果你选择保留现有的处理程序,不要让它们写入你的SaveConfiguration方法。*
在配置已经加载之后,改为以这种方式订阅事件:

  1. private void SubscribeToEvents()
  2. {
  3. foreach (var control in IterateControls(Controls))
  4. {
  5. if (control is TextBox textBox)
  6. {
  7. // You're still free to subscribe to these events
  8. // in other places for different purposes.
  9. textBox.TextChanged += (sender, e) =>
  10. SaveConfiguration(textBox, textBox.Text);
  11. }
  12. else if (control is NumericUpDown numeric)
  13. {
  14. numeric.ValueChanged += (sender, e) =>
  15. SaveConfiguration(numeric, numeric.Value);
  16. }
  17. else if (control is ComboBox comboBox)
  18. {
  19. comboBox.SelectionChangeCommitted += (sender, e) =>
  20. SaveConfiguration(comboBox, comboBox.SelectedIndex);
  21. }
  22. else if (control is TrackBar trackBar)
  23. {
  24. trackBar.ValueChanged += (sender, e) =>
  25. SaveConfiguration(trackBar, trackBar.Value);
  26. }
  27. else if (control is CheckBox checkBox)
  28. {
  29. checkBox.CheckedChanged += (sender, e) =>
  30. SaveConfiguration(checkBox, checkBox.Checked);
  31. }
  32. }
  33. }

保存单个控件更改

当发生更改时,只需序列化字典。就像写的那样,它不是非常有效。任何文本框中的每个字符串都会写入整个文件。因此,通过等待更改解决,异步写入配置文件,甚至在应用程序关闭时执行配置文件来优化。

  1. private void SaveConfiguration(Control control, object value)
  2. {
  3. ConfigurationHelper[control.Name] = value.ToString();
  4. // Save every change OR: - Save on app close? - Save after time delay (consolidate rapid changes)?
  5. File.WriteAllText(configPath, JsonConvert.SerializeObject(ConfigurationHelper));
  6. }

展开查看全部

相关问题