616 lines
22 KiB
C#
616 lines
22 KiB
C#
using Newtonsoft.Json;
|
|
using System;
|
|
using System.Collections.Concurrent;
|
|
using System.Collections.Generic;
|
|
using System.Data;
|
|
using System.Drawing;
|
|
using System.IO;
|
|
using System.IO.Ports;
|
|
using System.Linq;
|
|
using System.Threading;
|
|
using System.Windows.Forms;
|
|
using System.Xml.Linq;
|
|
using Xylem.Common.CommonCore.Consts;
|
|
using Xylem.Common.Hardware.Interfaces.Ports.PortCore.EventArguments;
|
|
using Xylem.Common.Hardware.Interfaces.Ports.SerialPorts;
|
|
using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisConfig;
|
|
using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore;
|
|
using Xylem.Common.Hardware.WaterMeter.WaterMeterCore;
|
|
using Xylem.Common.Utils.Logging;
|
|
|
|
namespace Xylem.Common.Ui.GenesisToolBox
|
|
{
|
|
public partial class FrmSetup : Form
|
|
{
|
|
private const String RequestPortString = "RequestPort";
|
|
private const String RequestTypeString = "RequestType";
|
|
private const String StreamingPortString = "StreamingPort";
|
|
private const String SlotTypeString = "RefTemperature";
|
|
private const String SlotString = "Slot";
|
|
private const String StreamingDetectString = "DetectStreaming";
|
|
private const String RequestDetectString = "DetectRequest";
|
|
private const String ValueString = "Value";
|
|
private const String TextString = "Text";
|
|
private String _fileString;
|
|
private readonly String _serialConfigFile;
|
|
private readonly DataTable _slotConfigDataTable = new DataTable();
|
|
|
|
|
|
private readonly ProcessConfig _configuration;
|
|
|
|
public FrmSetup()
|
|
{
|
|
_serialConfigFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
|
|
"Genesis", ProgramConfig.SerialConfigFileName);
|
|
|
|
//build header of data table for reference by name
|
|
_slotConfigDataTable.Columns.Add(SlotString, typeof(String));
|
|
_slotConfigDataTable.Columns.Add(StreamingPortString, typeof(String));
|
|
_slotConfigDataTable.Columns.Add(RequestPortString, typeof(String));
|
|
_slotConfigDataTable.Columns.Add(RequestTypeString, typeof(String));
|
|
_slotConfigDataTable.Columns.Add(SlotTypeString, typeof(String));
|
|
|
|
InitializeComponent();
|
|
tbcSlot.Name = SlotString;
|
|
cbcRequestPort.Name = RequestPortString;
|
|
cbcRequestType.Name = RequestTypeString;
|
|
cbcStreamingPort.Name = StreamingPortString;
|
|
cbcSlotType.Name = SlotTypeString;
|
|
btcDetectStreaming.Name = StreamingDetectString;
|
|
btcDetectRequest.Name = RequestDetectString;
|
|
btcDetectStreaming.Name = StreamingDetectString;
|
|
|
|
tbcSlot.HeaderText = SlotString;
|
|
cbcRequestPort.HeaderText = RequestPortString;
|
|
cbcRequestType.HeaderText = RequestTypeString;
|
|
cbcStreamingPort.HeaderText = StreamingPortString;
|
|
btcDetectRequest.HeaderText = RequestDetectString;
|
|
btcDetectStreaming.HeaderText = StreamingDetectString;
|
|
cbcSlotType.HeaderText = SlotTypeString;
|
|
|
|
LoadFromFile();
|
|
_configuration = new ProcessConfig(ProgramConfig.ConfigFileName);
|
|
cbUseMinMaxCheck.Checked = _configuration.UseMinMaxCheck;
|
|
cbUseRegisterWatch.Checked = _configuration.UseRegisterWatchService;
|
|
txtWachSeriveUrl.Text = _configuration.RegisterWatchServiceUrl;
|
|
cbUpdateFiles.Checked = _configuration.AutoUpdateFiles;
|
|
cbxProductionMode.Checked = _configuration.ProductionMode;
|
|
}
|
|
|
|
private void BtnReload_Click(Object sender, EventArgs e)
|
|
{
|
|
LoadFromFile();
|
|
LoadOfflineFile();
|
|
}
|
|
|
|
private void BtnStore_Click(Object sender, EventArgs e)
|
|
{
|
|
StoreToPc();
|
|
StoreOfflineFile();
|
|
}
|
|
|
|
private void StoreToPc()
|
|
{
|
|
var newFileContent = new List<SlotConfig>();
|
|
|
|
for (var row = 0; row < dgvConfig.Rows.Count; row++)
|
|
{
|
|
var slotStr = (String)dgvConfig.Rows[row].Cells[SlotString].Value;
|
|
int.TryParse(slotStr, out var slot);
|
|
|
|
|
|
var irdaType = typeof(IrdaSerialPort).FullName;
|
|
if (dgvConfig.Rows[row].Cells[RequestTypeString].Value != null)
|
|
{
|
|
irdaType = (String)dgvConfig.Rows[row].Cells[RequestTypeString].Value;
|
|
}
|
|
|
|
var requestPort = new PortConfig()
|
|
{
|
|
PortName = (String)dgvConfig.Rows[row].Cells[RequestPortString].Value,
|
|
Type = irdaType
|
|
};
|
|
|
|
var streamingPort = new PortConfig()
|
|
{
|
|
PortName = (String)dgvConfig.Rows[row].Cells[StreamingPortString].Value,
|
|
Type = typeof(UartSerialPort).FullName
|
|
};
|
|
|
|
var slotType = SlotType.DutMeter;
|
|
|
|
if (dgvConfig.Rows[row].Cells[SlotTypeString].Value != null)
|
|
{
|
|
var isChecked = dgvConfig.Rows[row].Cells[SlotTypeString].Value.ToString();
|
|
if (bool.TrueString == isChecked)
|
|
{
|
|
slotType = SlotType.TemperatureMeter;
|
|
}
|
|
}
|
|
|
|
if (!string.IsNullOrEmpty(slotStr))
|
|
{
|
|
newFileContent.Add(new SlotConfig()
|
|
{ Slot = slot, Request = requestPort, Streaming = streamingPort, Type = slotType });
|
|
}
|
|
}
|
|
|
|
var text = JsonConvert.SerializeObject(newFileContent);
|
|
// Overwrite only on changed content
|
|
if (text == _fileString)
|
|
{
|
|
LoadFromFile();
|
|
return;
|
|
}
|
|
|
|
//save file only on changed content
|
|
if (File.Exists(_serialConfigFile))
|
|
{
|
|
var backupSerialConfigFile = $"{Path.GetDirectoryName(_serialConfigFile)}" +
|
|
$"\\Backup_{DateTime.Now:yyyyMMdd}_{DateTime.Now:HHmmss}_{ProgramConfig.SerialConfigFileName}";
|
|
File.Move(_serialConfigFile, backupSerialConfigFile);
|
|
}
|
|
|
|
File.WriteAllText(_serialConfigFile, text);
|
|
LoadFromFile();
|
|
LoadOfflineFile();
|
|
}
|
|
|
|
private void LoadFromFile()
|
|
{
|
|
_slotConfigDataTable.Clear();
|
|
dgvConfig.Rows.Clear();
|
|
|
|
if (!File.Exists(_serialConfigFile))
|
|
{
|
|
return;
|
|
}
|
|
|
|
SlotConfig[] meterConfigList;
|
|
using (var tr = new StreamReader(_serialConfigFile))
|
|
{
|
|
_fileString = tr.ReadToEnd();
|
|
meterConfigList = JsonConvert.DeserializeObject<SlotConfig[]>(_fileString);
|
|
}
|
|
|
|
foreach (var item in meterConfigList)
|
|
{
|
|
var row = _slotConfigDataTable.NewRow();
|
|
row[SlotString] = item.Slot;
|
|
row[RequestPortString] = item.Request.PortName;
|
|
row[RequestTypeString] = item.Request.Type;
|
|
row[StreamingPortString] = item.Streaming.PortName;
|
|
row[SlotTypeString] = item.Type == SlotType.TemperatureMeter;
|
|
_slotConfigDataTable.Rows.Add(row);
|
|
}
|
|
|
|
foreach (DataRow row in _slotConfigDataTable.Rows)
|
|
{
|
|
dgvConfig.Rows.Add(AddRowToGrid(row));
|
|
}
|
|
}
|
|
|
|
private DataGridViewRow AddRowToGrid(DataRow row = null)
|
|
{
|
|
var newRow = new DataGridViewRow();
|
|
|
|
var slotCell = new DataGridViewTextBoxCell();
|
|
newRow.Cells.Add(slotCell);
|
|
|
|
var requestPortCell = new DataGridViewComboBoxCell
|
|
{
|
|
DataSource = GetPorts(),
|
|
DisplayMember = TextString,
|
|
ValueMember = ValueString
|
|
};
|
|
newRow.Cells.Add(requestPortCell);
|
|
|
|
|
|
var requestTypeCell = new DataGridViewComboBoxCell
|
|
{
|
|
DataSource = GetTypes(),
|
|
DisplayMember = TextString,
|
|
ValueMember = ValueString
|
|
};
|
|
newRow.Cells.Add(requestTypeCell);
|
|
|
|
var streamingPortCell = new DataGridViewComboBoxCell
|
|
{
|
|
DataSource = GetPorts(),
|
|
DisplayMember = TextString,
|
|
ValueMember = ValueString
|
|
};
|
|
newRow.Cells.Add(streamingPortCell);
|
|
|
|
|
|
var slotTypeCell = new DataGridViewCheckBoxCell();
|
|
slotTypeCell.Value = false;// SlotType.DutMeter.GetHashCode();
|
|
|
|
|
|
if (row == null)
|
|
{
|
|
return newRow;
|
|
}
|
|
|
|
slotCell.Value = row[SlotString];
|
|
streamingPortCell.Value = row[StreamingPortString];
|
|
requestPortCell.Value = row[RequestPortString];
|
|
|
|
try
|
|
{
|
|
requestTypeCell.Value = row[RequestTypeString];
|
|
}
|
|
catch (Exception)
|
|
{
|
|
// ignored
|
|
}
|
|
|
|
slotTypeCell.Value = row[SlotTypeString];// Enum.Parse(typeof(SlotType), row[_slotTypeString].ToString()).GetHashCode();
|
|
newRow.Cells.Add(slotTypeCell);
|
|
return newRow;
|
|
}
|
|
|
|
// ReSharper disable once UnusedMember.Local
|
|
private DataTable GetSlotTypes()
|
|
{
|
|
var ret = new DataTable();
|
|
ret.Columns.Add(TextString);
|
|
ret.Columns.Add(ValueString, typeof(Int32));
|
|
|
|
|
|
ret.Rows.Add("DutMeter", SlotType.DutMeter.GetHashCode());
|
|
ret.Rows.Add("TemperatureMeter", SlotType.TemperatureMeter.GetHashCode());
|
|
|
|
return ret;
|
|
}
|
|
|
|
private DataTable GetPorts()
|
|
{
|
|
var ret = new DataTable();
|
|
ret.Columns.Add(ValueString);
|
|
ret.Columns.Add(TextString);
|
|
var portList = SerialPort.GetPortNames().ToList();
|
|
|
|
foreach (var item in portList)
|
|
{
|
|
ret.Rows.Add(item, item);
|
|
}
|
|
|
|
foreach (DataRow row in _slotConfigDataTable.Rows)
|
|
{
|
|
if (portList.All(pl => pl != (String)row[StreamingPortString]))
|
|
{
|
|
ret.Rows.Add(row[StreamingPortString].ToString(), BaseSerialPort.PortNotAssigned);
|
|
}
|
|
if (portList.All(pl => pl != (String)row[RequestPortString]))
|
|
{
|
|
ret.Rows.Add(row[RequestPortString].ToString(), BaseSerialPort.PortNotAssigned);
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
private static DataTable GetTypes()
|
|
{
|
|
var ret = new DataTable();
|
|
ret.Columns.Add(ValueString);
|
|
ret.Columns.Add(TextString);
|
|
|
|
ret.Rows.Add(typeof(UartSerialPort).FullName, nameof(UartSerialPort));
|
|
ret.Rows.Add(typeof(RfidSerialPort).FullName, nameof(RfidSerialPort));
|
|
ret.Rows.Add(typeof(IrdaSerialPort).FullName, nameof(IrdaSerialPort));
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private ConcurrentBag<String> _countRawData = new ConcurrentBag<String>();
|
|
|
|
private void DgvConfig_CellContentClick(Object sender, DataGridViewCellEventArgs e)
|
|
{
|
|
if (!dgvConfig.Columns[e.ColumnIndex].Name.Contains(StreamingDetectString) &&
|
|
!dgvConfig.Columns[e.ColumnIndex].Name.Contains(RequestDetectString))
|
|
{
|
|
return;
|
|
}
|
|
|
|
StoreToPc();
|
|
|
|
var slotString = (String)dgvConfig.Rows[e.RowIndex].Cells[SlotString].Value;
|
|
int.TryParse(slotString, out var slot);
|
|
|
|
using (var mb = new MeterBatch())
|
|
{
|
|
using (var meter = new GenesisMeter())
|
|
{
|
|
meter.SetupFromConfigFile(slot, false);
|
|
mb.AddMeter(meter);
|
|
|
|
const String checkMark = "\u2714";
|
|
|
|
if (dgvConfig.Columns[e.ColumnIndex].Name.Contains(StreamingDetectString))
|
|
{
|
|
_countRawData = new ConcurrentBag<String>();
|
|
|
|
meter.StreamingPort.OnRawRecordReceived += delegate (Object o, BasePortDataEventArgs rawMsg)
|
|
{
|
|
_countRawData.Add((String)rawMsg.GetData());
|
|
};
|
|
|
|
Thread.Sleep(500);
|
|
|
|
if (_countRawData.Any())
|
|
{
|
|
var text = $"SUCCESS\nSlot: {slot}\nStreaming port: {meter.StreamingPort.GetPortName()}\n\n{checkMark}";
|
|
MessageBox.Show(text, @"SUCCESS", MessageBoxButtons.OK);
|
|
dgvConfig.Rows[e.RowIndex].Cells[StreamingDetectString].Style.BackColor = Color.Green;
|
|
}
|
|
else
|
|
{
|
|
var text = $"FAILED\nSlot: {slot}\nStreaming port: {meter.StreamingPort.GetPortName()}";
|
|
MessageBox.Show(text, @"FAILED", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
dgvConfig.Rows[e.RowIndex].Cells[StreamingDetectString].Style.BackColor = Color.Red;
|
|
}
|
|
|
|
_countRawData = new ConcurrentBag<String>();
|
|
}
|
|
else
|
|
{
|
|
meter.Logout();
|
|
var pcbId = meter.GetPcbId();
|
|
if (string.IsNullOrEmpty(pcbId))
|
|
{
|
|
var text = $"FAILED\nSlot: {slot}\nRequest port: {meter.RequestPort.GetPortName()}";
|
|
MessageBox.Show(text, @"FAILED", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
dgvConfig.Rows[e.RowIndex].Cells[RequestDetectString].Style.BackColor = Color.Red;
|
|
}
|
|
else
|
|
{
|
|
var text = $"SUCCESS\nSlot: {slot}\nRequest port: {meter.RequestPort.GetPortName()}\n\n{checkMark}";
|
|
MessageBox.Show(text, @"SUCCESS", MessageBoxButtons.OK);
|
|
dgvConfig.Rows[e.RowIndex].Cells[RequestDetectString].Style.BackColor = Color.Green;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private void dgvConfig_DataError(Object sender, DataGridViewDataErrorEventArgs e)
|
|
{
|
|
|
|
}
|
|
|
|
private void cbUseRegisterWatch_CheckedChanged(Object sender, EventArgs e)
|
|
{
|
|
_configuration.UseRegisterWatchService = cbUseRegisterWatch.Checked;
|
|
_configuration.Update(ProgramConfig.ConfigFileName);
|
|
StoreToPc();
|
|
}
|
|
|
|
private void cbUseMinMaxCheck_CheckedChanged(Object sender, EventArgs e)
|
|
{
|
|
_configuration.UseMinMaxCheck = cbUseMinMaxCheck.Checked;
|
|
_configuration.Update(ProgramConfig.ConfigFileName);
|
|
StoreToPc();
|
|
}
|
|
|
|
private void textBox1_TextChanged(Object sender, EventArgs e)
|
|
{
|
|
_configuration.RegisterWatchServiceUrl = txtWachSeriveUrl.Text;
|
|
_configuration.Update(ProgramConfig.ConfigFileName);
|
|
StoreToPc();
|
|
}
|
|
|
|
private void cbUpdateFiles_CheckedChanged(Object sender, EventArgs e)
|
|
{
|
|
_configuration.AutoUpdateFiles = cbUpdateFiles.Checked;
|
|
_configuration.Update(ProgramConfig.ConfigFileName);
|
|
StoreToPc();
|
|
}
|
|
|
|
private List<OfflinePaswordItem> _listOfOfflinePasswords = new List<OfflinePaswordItem>();
|
|
|
|
|
|
private void FrmSetup_Load(Object sender, EventArgs e)
|
|
{
|
|
LoadOfflineFile();
|
|
cbxProductionMode.CheckedChanged += cbxProductionMode_CheckedChanged;
|
|
|
|
}
|
|
|
|
|
|
|
|
private void StoreOfflineFile()
|
|
{
|
|
try
|
|
{
|
|
// remove empty cells
|
|
var listToRemove = _listOfOfflinePasswords.Where(offlinePwd => string.IsNullOrEmpty(offlinePwd.PcbID)).ToList();
|
|
foreach (var itemToRemove in listToRemove)
|
|
{
|
|
_listOfOfflinePasswords.Remove(itemToRemove);
|
|
}
|
|
File.WriteAllText(ProgramConfig.OfflineInfoFile, JsonConvert.SerializeObject(_listOfOfflinePasswords));
|
|
dgvofflinePw.CellValidated -= dgvofflinePw_CellValidated;
|
|
dgvofflinePw.DataSource = null;
|
|
dgvofflinePw.DataSource = _listOfOfflinePasswords;
|
|
dgvofflinePw.CellValidated += dgvofflinePw_CellValidated;
|
|
}
|
|
catch (Exception)
|
|
{
|
|
// ignored
|
|
}
|
|
}
|
|
|
|
private void LoadOfflineFile()
|
|
{
|
|
try
|
|
{
|
|
_listOfOfflinePasswords = JsonConvert.DeserializeObject<List<OfflinePaswordItem>>(File.ReadAllText(ProgramConfig.OfflineInfoFile));
|
|
|
|
}
|
|
catch (Exception)
|
|
{
|
|
_listOfOfflinePasswords = new List<OfflinePaswordItem>();
|
|
}
|
|
finally
|
|
{
|
|
|
|
dgvofflinePw.CellValidated -= dgvofflinePw_CellValidated;
|
|
dgvofflinePw.DataSource = null;
|
|
dgvofflinePw.DataSource = _listOfOfflinePasswords;
|
|
dgvofflinePw.CellValidated += dgvofflinePw_CellValidated;
|
|
}
|
|
|
|
}
|
|
|
|
private void dgvofflinePw_CellValidated(Object sender, DataGridViewCellEventArgs e)
|
|
{
|
|
StoreOfflineFile();
|
|
}
|
|
|
|
private void cmdAddOffline_Click(Object sender, EventArgs e)
|
|
{
|
|
_listOfOfflinePasswords.Add(new OfflinePaswordItem("", ""));
|
|
|
|
dgvofflinePw.DataSource = null;
|
|
dgvofflinePw.DataSource = _listOfOfflinePasswords;
|
|
}
|
|
|
|
private void cbxProductionMode_CheckedChanged(Object sender, EventArgs e)
|
|
{
|
|
if (cbxProductionMode.Checked)
|
|
{
|
|
MessageBox.Show(@"Production mode!Configraution.json muss zwingend dem Aktuellen Release entsprechen! ");
|
|
}
|
|
else
|
|
{
|
|
MessageBox.Show(@"Developer mode!Configraution.json muss nicht zwingend auf aktuellen Release entsprechen. Es wird die letzte gültige Configraution.json anwendet.Dies führt dazu dass Grenzwerte nicht sauber überprüft werden und ggf. Register nicht sichtbar sind die der Zähler unterstützt. ");
|
|
}
|
|
|
|
_configuration.ProductionMode = cbxProductionMode.Checked;
|
|
_configuration.Update(ProgramConfig.ConfigFileName);
|
|
StoreToPc();
|
|
|
|
}
|
|
|
|
private void tabPage4_Click(Object sender, EventArgs e)
|
|
{
|
|
try
|
|
{
|
|
var path = NLogHelper.GetCurrentApplicationFolder();
|
|
var a = XElement.Load(path);
|
|
lblLocalCurrentPath.Text = a.Elements().First(s => s.Name.LocalName == "variable").Attributes().First(s => s.Value == "BasePath").NextAttribute.Value;
|
|
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
lblLocalCurrentPath.Text = ex.Message;
|
|
}
|
|
|
|
try
|
|
{
|
|
var path = NLogHelper.GetApplicationDataPath();
|
|
var b = XElement.Load(path);
|
|
lblGlobalCurrentPath.Text = b.Elements().First(s => s.Name.LocalName == "variable").Attributes().First(s => s.Value == "BasePath").NextAttribute.Value;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
lblGlobalCurrentPath.Text = ex.Message;
|
|
}
|
|
}
|
|
|
|
private void Add(String path, String newDest)
|
|
{
|
|
try
|
|
{
|
|
var a = XElement.Load(path);
|
|
var firstIsVariable = a.Elements().First();
|
|
if (firstIsVariable.Name.LocalName != "variable" )
|
|
{
|
|
var newElm = new XElement("variable", null);
|
|
newElm.SetAttributeValue("name", "BasePath");
|
|
newElm.SetAttributeValue("value", newDest);
|
|
a.AddFirst(newElm);
|
|
}
|
|
|
|
else if (a.Elements().First(b => b.Name.LocalName == "variable").Attributes()
|
|
.All(s => s.Value != "BasePath"))
|
|
{
|
|
var newElm = new XElement("variable", null);
|
|
newElm.SetAttributeValue("name", "BasePath");
|
|
newElm.SetAttributeValue("value", newDest);
|
|
a.AddFirst(newElm);
|
|
}
|
|
else
|
|
{
|
|
a.Elements().First(b => b.Name.LocalName == "variable").Attributes()
|
|
.First(s => s.Value == "BasePath").NextAttribute.Value = newDest;
|
|
|
|
}
|
|
|
|
a.Save(path);
|
|
tabPage4_Click(this, null);
|
|
}
|
|
catch (Exception)
|
|
{
|
|
// ignore;
|
|
}
|
|
}
|
|
private void btnLocalDefaultLocal_Click(Object sender, EventArgs e)
|
|
{
|
|
Add(NLogHelper.GetCurrentApplicationFolder(), "C:\\GenesisLog\\");
|
|
|
|
}
|
|
|
|
private void btnLocalDefaultLan_Click(Object sender, EventArgs e)
|
|
{
|
|
Add(NLogHelper.GetCurrentApplicationFolder(), "\\\\sla12buma\\cordonelds$\\${machinename}");
|
|
}
|
|
|
|
private void btnGlobalDefaultLocal_Click(Object sender, EventArgs e)
|
|
{
|
|
Add(NLogHelper.GetApplicationDataPath(), "C:\\GenesisLog\\");
|
|
}
|
|
|
|
private void btnGlobalDefaultLan_Click(Object sender, EventArgs e)
|
|
{
|
|
Add(NLogHelper.GetApplicationDataPath(), "\\\\sla12buma\\cordonelds$\\${{machinename}}");
|
|
}
|
|
|
|
private void btnGlobalSearch_Click(Object sender, EventArgs e)
|
|
{
|
|
var dia = new FolderBrowserDialog();
|
|
|
|
dia.ShowDialog();
|
|
|
|
Add(NLogHelper.GetApplicationDataPath(), dia.SelectedPath);
|
|
|
|
|
|
}
|
|
|
|
private void btnLocalSearch_Click(Object sender, EventArgs e)
|
|
{
|
|
var dia = new FolderBrowserDialog();
|
|
|
|
dia.ShowDialog();
|
|
|
|
Add(NLogHelper.GetCurrentApplicationFolder(), dia.SelectedPath);
|
|
}
|
|
|
|
private void btnAddRow_Click(Object sender, EventArgs e)
|
|
{
|
|
dgvConfig.Rows.Add(AddRowToGrid());
|
|
}
|
|
}
|
|
}
|