(NET) NET (2015)

DataGridView-редактор параметрів програми.

Параметри роботи десктопних програм можна зберігати у реестрі (Простий сервіс реестра для зберігання вводу користувача десктопних прог), але зберігати там багато даних незручно, тому можна зберігати у реестрі лише лінк на файл з параметрами. До того ж, можна зробити достатньо зручний редактор параметрів на базі DataGridView, саме тих параметрів, що потрібні конкретному юзеру для роботи. Нище я покажу свій шаблон коду, як це робиться.



I.

Цей типовий шаблон декстопних програм починається з якогось файліку з параметрами роботи програми, який існує у проєкті.



У кінцевому вигляді, у моєму випадку цей файлік використовується як довідник, він у відкритому текстовому вигляді використувується бекапиться разом з усіма даними юзера, до того ж треба надати юзеру можливість найпростішим засобом редактувати цей справочник, додавати або видаляти записи. Це, власно кажучи, і є умови використання цього патерна.



Лінк на довідник зберігається у реестрі.



Коли перша форма завантажуєтся, лінк на цей файлік вичитується з реестра у змінну, та у подальшому використовується на наступних формах.


   5:  Public Class LoginForm
  ...   
  13:      Public Shared UrlTypeFileName As String
  14:   
  15:      Private Sub LoginForm_Load(sender As Object, e As EventArgs) Handles Me.Load
  ...   
  20:          UrlTypeFileName = MyRegistry.GetValue(Of String)("UrlTypeFileName")

Власне код використання цього довідника у Combox'і другої форми виглядає ось так.


  54:      Public Sub TypeComboBox_Refresh()
  55:          Dim UrlTypeFileLines = IO.File.ReadAllLines(LoginForm.UrlTypeFileName)
  56:          RowType = New List(Of String)(UrlTypeFileLines)
  57:          TypeComboBox.ComboBox.DataSource = RowType
  ...   
  60:      End Sub

Оскільки прога ставиться у Program Files, де змінювати файли заборонено, а по умовам цей файлік треба дозволити змінювати юзеру, нам потрібно десь вставити код, який при першому запуску програми скопірує цей файлік у каталог, де його редактовання не заборонено.


  46:      Function GetUrlTypeFileName() As String
  47:          Dim LocalTmpPath As String = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)
  48:          Dim TempAppDirectory As String = IO.Path.Combine(LocalTmpPath, Application.ProductName)
  49:          If My.Computer.FileSystem.DirectoryExists(TempAppDirectory) Then
  50:              My.Computer.FileSystem.CreateDirectory(TempAppDirectory)
  51:          End If
  52:          Return IO.Path.Combine(TempAppDirectory, "Type.txt")
  53:      End Function
  54:   
  56:      Sub FirstStart()
  57:          UrlTypeFileName = GetUrlTypeFileName()
  58:          My.Computer.FileSystem.CopyFile(IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Type.txt"), UrlTypeFileName)
  59:          MyRegistry.SetValue("UrlTypeFileName",UrlTypeFileName)
  ...   
  63:      End Sub

First start тут відрацьовує при першому завантаженню програми, у кінцевому вигляді це визначається по відсутністі у реестре ключей, пов'язаних з програмою, і файлік копірується у доступне для редактування місце..



II.

Тепер, коли ми знаємо, що це за файлік, як він використовується, та як він з'явився у TempDirectory нашої програми, давайте з'ясуємо як користувач програми може його змінювати.

Тобто зараз ми подивимося на код форми редактора, а щоб ви зрозуміли імена зміних, я вам їх покажу на скрині. Також ось вам налаштування DataGridView у дізайнері.



 298:          '
 299:          'DataGridView1
 300:          '
 301:          Me.DataGridView1.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.Fill
 302:          Me.DataGridView1.AutoSizeRowsMode = System.Windows.Forms.DataGridViewAutoSizeRowsMode.AllCells
 303:          Me.DataGridView1.ColumnHeadersBorderStyle = System.Windows.Forms.DataGridViewHeaderBorderStyle.[Single]
 304:          Me.DataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize
 305:          Me.DataGridView1.Dock = System.Windows.Forms.DockStyle.Fill
 306:          Me.DataGridView1.Location = New System.Drawing.Point(0, 0)
 307:          Me.DataGridView1.MultiSelect = False
 308:          Me.DataGridView1.Name = "DataGridView1"
 309:          Me.DataGridView1.RowHeadersVisible = False
 310:          Me.DataGridView1.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect
 311:          Me.DataGridView1.Size = New System.Drawing.Size(267, 170)
 312:          Me.DataGridView1.TabIndex = 0

І ось, нарешті, ми дойшли до самого цікавого, до коду редактора. Тут все починається з окремого файліку, бо безпосередньо завантажити текстовий файлік як біндінг DataGridView неможливо, тому що String має лише один параметр - length, і DatagridView прибіндиться лише до цього свойства.

Тому у першу чергу нам доведеться зробити окремий клас StringValue, у якого буде свойство Value, до якого можна прібіндити DataGrivView.


   1:  Public Class StringValue
   2:      Private _value As String
   3:      Public Sub New(ByVal s As String)
   4:          _value = s
   5:      End Sub
   6:   
   7:      Public Property Value As String
   8:          Get
   9:              Return _value
  10:          End Get
  11:          Set(ByVal value As String)
  12:              _value = value
  13:          End Set
  14:      End Property
  15:  End Class

Лише тепер можна визначити список для біндінга, вичитати файл з того місяці, яке зафіксовано у нас на першої формі, як лінк на файлік-довідник (LoginForm.UrlTypeFileName) у TempDirectory програми, який ми бажаємо редактувати, зробити перетворення текста у список StringValue у стрічці 141 за допомогою Action у ForEach, та нарешті завантажити BindingList(Of StringValue) у DataGridView (у стрічці 39).


  ...   
   6:  Public Class Setting
  ...   
   9:      Public Property DataSource As BindingList(Of StringValue)
  ...   
  12:      Private Sub Setting_Load(sender As Object, e As EventArgs) Handles Me.Load
  ...   
  38:          DataSource = ReadUrlTypeFile(LoginForm.UrlTypeFileName)
  39:          DataGridView1.DataSource = DataSource
  40:      End Sub
 ...    
 137:      Function ReadUrlTypeFile(FileName As String) As BindingList(Of StringValue)
 138:          Dim KeyFile = IO.File.ReadAllLines(FileName)
 139:          Dim KeyList = New List(Of String)(KeyFile)
 140:          Dim KeyValueList = New BindingList(Of StringValue)
 141:          KeyList.ForEach(Sub(Y) KeyValueList.Add(New StringValue(Y)))
 142:          Return KeyValueList
 143:      End Function
 144:   

Ось, нарешті обробка трьох евентів, по трьом кнопках - Add/Remove/Save - які розміщені нан тулбарі над DataGridView.


 172:      Private Sub AddToolStripButton_Click(sender As Object, e As EventArgs) Handles AddToolStripButton.Click
 173:          DataSource.Add(New StringValue(""))
 174:          DataGridView1.EditEndRow
 175:      End Sub
 176:   
 177:      Private Sub RemoveToolStripButton_Click(sender As Object, e As EventArgs) Handles RemoveToolStripButton.Click
 178:          If DataGridView1.SelectedRows.Count > 0 Then
 179:              DataGridView1.Rows.RemoveAt(DataGridView1.SelectedRows(0).Index)
 180:          End If
 181:      End Sub
 182:   
 183:      Private Sub SaveToolStripButton_Click(sender As Object, e As EventArgs) Handles SaveToolStripButton.Click
 184:          Dim TxtResult As New Text.StringBuilder
 185:          For Each One As StringValue In DataSource
 186:              TxtResult.AppendLine(One.Value)
 187:          Next
 188:          My.Computer.FileSystem.WriteAllText(LoginForm.UrlTypeFileName, TxtResult.ToString, False)
 189:          If StartForm IsNot Nothing Then
 190:              StartForm.TypeComboBox_Refresh()
 191:          End If
 192:          AutoClosingMessageBox.Show("Saved")
 193:      End Sub

Але це все не все, по-перше у стрічці 192 викликається AutoClosingMessageBox, який на короткий час вспливає та звертає увагу юзера, що нові дані збережені. Ця бібліотечка ставиться з https://www.nuget.org/packages/AutoClosingMessageBox/.

А по-друге у стрічці тут є важлива Extension-функція EditEndRow, яка фіксує фокус ввода у поле ввода при введенні нових даних.

Як будь-яка Extension-функция, вона визначається у окремому модулі, і виглядає вона ось так.


   1:  Imports System.Runtime.CompilerServices
   2:   
   3:  Module Extensions4
   4:      <Extension()>
   5:      Sub EditEndRow(Grid As DataGridView)
   6:          Grid.ClearSelection()
   7:          Grid.Rows(Grid.Rows.Count - 1).Selected = True
   8:          Grid.CurrentCell = Grid(0, Grid.Rows.Count - 1)
   9:          Grid.CurrentCell.Selected = True
  10:          Grid.FirstDisplayedScrollingRowIndex = Grid.Rows.Count - 1
  11:          Grid.Focus()
  12:          Grid.BeginEdit(False)
  13:      End Sub
  14:  End Module


<00>  <01>  <02>  <03>  <04>  <05>  <06>  <07>  <08>  <09>  <10>  <11>  <12>  <13>  <14>  <15>  <16>  <17>  <18>  <19>  <20>  <21>  <22>  <23
<SITEMAP>  <MVC>  <ASP>  <NET>  <DATA>  <KIOSK>  <FLEX>  <SQL>  <NOTES>  <LINUX>  <MONO>  <FREEWARE>  <DOCS>  <ENG>  <CHAT ME>  <ABOUT ME>  < THANKS ME>