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
<SITEMAP> <MVC> <ASP> <NET> <DATA> <KIOSK> <FLEX> <SQL> <NOTES> <LINUX> <MONO> <FREEWARE> <DOCS> <ENG> <CHAT ME> <ABOUT ME> < THANKS ME> |