Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > .NET для новичков > где хранить имя файла


Автор: vasjon 11.11.2007, 10:59
Собираюсь сделать возможность открывать (выбирать) файл БД через openFileDialog, примерно представляю как я это сделаю, но вижу проблему: где сохранять (хранить) имя последнего открытого файла (выбраного) файла БД ? В файле ? В конфиграционном файле ? Если можно пример кода для сохраненния имени и востановления его.

Автор: thomas 11.11.2007, 11:48
vasjon
Привет.
Недавно писал на VB.NET программку работающую с БД.
Для хранения настроек программы использовал новую фичу от MS - My.Settings.
Т.е. настройки программы хранятся в файле user.config для каждого пользователя.
Редактировать их пользователь может через PropertyGrid который я выводил в отдельной форме.
Код формы:
Код

Public Class frmSettings

    Private Sub frmSettings_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        grdSettings.SelectedObject = My.Settings
    End Sub

    Private Sub frmSettings_FormClosing(ByVal sender As System.Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles MyBase.FormClosing
        My.Settings.Save()
    End Sub

End Class

Чтобы получить нужные настройки программы идем во вкладку Settings  свойств проекта. Там прописываем нужные настройки, но значения не указываем. Их укажет пользователь при старте программы.
Далее нужно подредактировать сгенерированный студией файл  Settings.Designer.vb.
Используя аттрибуты свойств указывает к какой группе они относятся, коментарии, отображать или нет.
Выглядит это примерно так
Код

Option Strict On
Option Explicit On


Namespace My

    <Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(), _
     Global.System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "8.0.0.0"), _
     Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
    Partial Friend NotInheritable Class MySettings
        Inherits Global.System.Configuration.ApplicationSettingsBase

        Private Shared defaultInstance As MySettings = CType(Global.System.Configuration.ApplicationSettingsBase.Synchronized(New MySettings), MySettings)

#Region "My.Settings Auto-Save Functionality"
#If _MyType = "WindowsForms" Then
        Private Shared addedHandler As Boolean

        Private Shared addedHandlerLockObject As New Object

        <Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
        Private Shared Sub AutoSaveSettings(ByVal sender As Global.System.Object, ByVal e As Global.System.EventArgs)
            If My.Application.SaveMySettingsOnExit Then
                My.Settings.Save()
            End If
        End Sub
#End If
#End Region

        Public Shared ReadOnly Property [Default]() As MySettings
            Get

#If _MyType = "WindowsForms" Then
                If Not addedHandler Then
                    SyncLock addedHandlerLockObject
                        If Not addedHandler Then
                            AddHandler My.Application.Shutdown, AddressOf AutoSaveSettings
                            addedHandler = True
                        End If
                    End SyncLock
                End If
#End If
                Return defaultInstance
            End Get
        End Property

'то что между "<" ">" это аттрибуты, дописывал сам
        <Global.System.ComponentModel.CategoryAttribute("Application"), _
         Global.System.Configuration.ApplicationScopedSettingAttribute(), _
         Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
         Global.System.Configuration.SpecialSettingAttribute(Global.System.Configuration.SpecialSetting.ConnectionString), _
         Global.System.Configuration.DefaultSettingValueAttribute("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=""D:\MyProjects\MAIL ID\Mailing1\Mail" & _
            "ing.mdb""")> _
        Public ReadOnly Property MailingConnectionString() As String
            Get
                Return CType(Me("MailingConnectionString"), String)
            End Get
        End Property

'то что между "<" ">" это аттрибуты, дописывал сам
<Global.System.ComponentModel.CategoryAttribute("Application"), _
         Global.System.ComponentModel.DescriptionAttribute("Naam van database bestand die zal gebruikt worden in dit programma."), _
         Global.System.Configuration.UserScopedSettingAttribute(), _
         Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
         Global.System.Configuration.DefaultSettingValueAttribute(""), _
         Global.System.ComponentModel.EditorAttribute(GetType(clsFileNameEditor), GetType(System.Drawing.Design.UITypeEditor))> _
        Public Property DataBase() As String
            Get
                Return CType(Me("DataBase"), String)
            End Get
            Set(ByVal value As String)
                Me("DataBase") = Value
            End Set
        End Property

'эту функцию дописал сам, она переписывает значение свойства connectionString используя редактируемое пользователем свойство DataBase().
        Public Function SetUserOverride() As String
            Me("MailingConnectionString") = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & Chr(34) & Me.DataBase & Chr(34)
            Return Me("MailingConnectionString").ToString()
        End Function
    End Class
End Namespace

В моем случае, использовался TypedDataSet которому студия задает соединение в designermode и оно прописывается в app.config и во время работы программы изменению не подлежит.
Вот чтобы это обойти и дать возможность пользователю самому указывать где лежит его база данных и сохранить это в его настройках(user.config) и забить болт на app.config, я и дописал функцию SetUserOverride(). Она берет значение указанное пользователем и переписывает значение connectionString, подставляя туда путь к БД(runtime) вместо прописанного в designermode.
А чтобы пользователь не писал путь в БД и ее имя в ручную добавляем в PropertuGrid кнопочку с точечками, которая откроет OpenFileDialog для выбора файла БД.
Для этого свойству DataBase() добавим аттрибут
Код

Global.System.ComponentModel.EditorAttribute(GetType(clsFileNameEditor), GetType(System.Drawing.Design.UITypeEditor))

Для которого напишем следующий класс Editor
Код

Public Class clsFileNameEditor
    Inherits Global.System.Drawing.Design.UITypeEditor

    Public Overrides Function GetEditStyle(ByVal context As System.ComponentModel.ITypeDescriptorContext) As Global.System.Drawing.Design.UITypeEditorEditStyle
        Return Global.System.Drawing.Design.UITypeEditorEditStyle.Modal
    End Function

    Public Overrides Function EditValue(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal provider As System.IServiceProvider, ByVal value As Object) As Object

        Dim f As New OpenFileDialog()
        f.Filter = "Access File(*.mdb)|*.mdb"
        f.ShowDialog()
        Return f.FileName
    End Function
End Class

Вот таким образом я решил эту проблемку.
Да маленькое замечание.
Класс Settings.Designer.vb сгенерирован студией, и если вы после всех внесенных в него изменений за каким то лядом полезете во вкладку Settings свойств проекта и что-то там поменяете, то студия сгенерит этот класс по новой и все ваши труды пропадут.
А по сему сначала думаем, а потом делаем. Или пишем добавки в этому классу в класс Settings.vb это Partial класс -  вторая половинка класса Settings.Designer.vb.

Успехов.  smile 
Надеюсь инфа пригодиться в том или ином случае. smile 


Автор: vasjon 11.11.2007, 17:56
спасибо конечно, но я знаю только C#... в VB могу легкие примеры понять... но вот какой вопрос, а изменить значения в app.config программно я так понимаю нельзя ?

Автор: thomas 11.11.2007, 23:27
vasjon
Привет.
Цитата

изменить значения в app.config программно я так понимаю нельзя ? 

По идее нет, но если очень хочеться то можно попробовать "танцы с бубнами". 
App.config это xml файл. Соответственно  используя классы и методы из пространства имен System.XML можно читать и записывать данные из/в xml-файлы.

Разница между синтаксисом VB и C# конечно есть, но суть то одна и таже.
Используя вкладку Settings  свойст твоего проекта ты получишь сгенерированный студией файл аналогичный Settings.Designer.vb, но только уже в C#.
Добавь туда же нужные тебе аттрибуты свойств класса, допиши простую функцию и напиши коротенький класс для Editor. И всё, дело в шляпе.

Автор: 1stain 12.11.2007, 00:31
что-то я не совсем понял про танцы с бубном вокруг app.config...
насколько я понимаю, он отражается в program_name.exe.config, который программно можно прочитать через ConfigurationManager, модифицировать что надо и записать.

примерно так:

Автор: vasjon 12.11.2007, 15:33
1stain то что надо, спасибо.
А добавлять новые ключи в этот файл можно ?
И еще я только начинаю изучать C# не могли бы пояснить:
Код

List<ConnectionStringSettings> connStrings;

Автор: thomas 12.11.2007, 15:54
vasjon
Это означает что
обьект connStrings имеет тип List<ConnectionStringSettings>
где List является списком обьектов типа ConnectionStringSettings



Автор: vasjon 12.11.2007, 15:57
и вам спасибо добрый человек smile , будем знать

Добавлено через 5 минут и 1 секунду
а добавление ключей программно возможно ?

Автор: 1stain 12.11.2007, 16:37
Цитата(vasjon @  12.11.2007,  15:33 Найти цитируемый пост)
А добавлять новые ключи в этот файл можно ?

все можно
добавь к процедуре клика по Ok перед записью конфига такое: 
Код

config.ConnectionStrings.ConnectionStrings.Add(new ConnectionStringSettings("Preved_medved", @"Data Source=.\MSSQL2005;Initial Catalog=Northwind;Integrated Security=True;Asynchronous Processing=True;", "System.Data.SqlClient"));


з.ы. и такое
Код

config.AppSettings.Settings.Add("Preved_Key", "Preved, medved!");


и посмотри файл WindowsApplication1.exe.config


Автор: thomas 12.11.2007, 16:54
1stain
Привет.
Посмотрел твой пример.
После выполнения програмки с изменением БД в списке, открываю WindowsApplication1.exe.config, а там как был LocalSqlServer так и остался.
 smile

Добавлено через 1 минуту и 49 секунд
И потом если vasjon, использует VS 2005, то надо бы использовать новые возможности, а не методы из FW 1.1.

Автор: vasjon 12.11.2007, 16:56
спасибо за помощь
у меня кстати все работает из примера 1stain
студия 2005, но вкладку Settings я так и не нашел

Автор: 1stain 12.11.2007, 16:57
ты "Ок" жмакал? открываешь именно WindowsApplication1.exe.config тот который рядом с экзешником лежит?

не путать с WindowsApplication1.vshost.exe.config

и уж тем более не путать с App.config smile

Добавлено через 7 минут и 7 секунд
Цитата(thomas @  12.11.2007,  16:54 Найти цитируемый пост)
И потом если vasjon, использует VS 2005, то надо бы использовать новые возможности, а не методы из FW 1.1.

 smile 
Код

.NET Framework Class Library  
ConfigurationManager Class 

Note: This class is new in the .NET Framework version 2.0. 

Provides access to configuration files for client applications. This class cannot be inherited. 


Код

.NET Framework Class Library  
ConnectionStringsSection Class  

Note: This class is new in the .NET Framework version 2.0. 

Provides programmatic access to the connection strings configuration-file section. 


Код

.NET Framework Class Library  
AppSettingsSection Class 

Note: This class is new in the .NET Framework version 2.0. 


это все из MSDN кроме того, если мне будет удобнее, то я буду юзать хоть ассемблер (даже притом, что йа его не знайу  smile )

Автор: thomas 12.11.2007, 17:23
vasjon
Цитата

студия 2005, но вкладку Settings я так и не нашел

В SolutionExplorer жми правой кнопкой по названию аликации, в контекстном меню в самом низу выбираем Properties.
Открывается окно со свойствами проекта, слева вкладки(расположены вертикально).


Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)