[C#] WPF 응용 프로그램에서 사용자 설정을 저장하는 방법?


Answers

설정 정보를 XML StringsSettings.Default 저장할 수 있습니다. 구성 데이터를 저장할 클래스를 몇 개 만들고 [Serializable] 인지 확인하십시오. 다음 헬퍼를 사용하면 이러한 객체의 인스턴스 ( List<T> 또는 배열 T[] 등)를 String serialize 할 수 있습니다. 이 다양한 문자열 각각을 WPF 응용 프로그램 Settings.Default 의 자체 Settings.Default 슬롯에 저장하십시오.

다음에 앱이 시작될 때 개체를 복구하려면 관심있는 Settings 문자열을 읽고 원하는 형식 T Deserialize 하십시오 (이 시간은 Deserialize<T> 의 형식 인수로 명시 적으로 지정해야 함).

public static String Serialize<T>(T t)
{
    using (StringWriter sw = new StringWriter())
    using (XmlWriter xw = XmlWriter.Create(sw))
    {
        new XmlSerializer(typeof(T)).Serialize(xw, t);
        return sw.GetStringBuilder().ToString();
    }
}

public static T Deserialize<T>(String s_xml)
{
    using (XmlReader xw = XmlReader.Create(new StringReader(s_xml)))
        return (T)new XmlSerializer(typeof(T)).Deserialize(xw);
}
Question

WPF 윈도우 (데스크톱) 응용 프로그램에서 사용자 설정을 지속하기 위해 어떤 접근 방식을 권장합니까? 사용자가 런타임에 설정을 변경 한 다음 응용 프로그램을 닫을 수 있고 나중에 응용 프로그램을 시작할 때 응용 프로그램이 현재 설정을 사용한다는 아이디어가 있습니다. 그러면 응용 프로그램 설정이 변경되지 않는 것처럼 효과적으로 나타납니다.

Q1 - 데이터베이스 또는 다른 접근법? 내가 어쨌든 데이터베이스에서 테이블을 사용하여 어떤 접근 방식으로 좋을 것이 사용됩니다 sqlite 데이터베이스가 있나요?

Q2 - 데이터베이스 인 경우 : 어떤 데이터베이스 테이블 디자인입니까? 하나의 테이블 (예 : string , long , DateTime 등) 또는 값을 직렬화 및 비 직렬화해야하는 값에 대한 문자열이있는 테이블을 가질 수있는 다른 데이터 유형에 대한 열이 있습니까? 첫 번째가 더 쉬울 것이라고 생각하고, 설정이 많지 않으면 오버 헤드가별로 없습니까?

Q3 - 응용 프로그램 설정을이 용도로 사용할 수 있습니까? 그렇다면 여기에 지속성을 활성화하는 데 필요한 특별한 작업이 있습니까? 이 경우 응용 프로그램 설정 디자이너에서 "기본값"값을 다시 사용하면 어떻게됩니까? 기본값은 응용 프로그램 실행 사이에 저장된 모든 설정을 무시합니까? (또는 기본값을 사용하지 않아도됩니다)




이 질문에 대한 장기적으로 가장 일반적인 접근 방식은 다음과 같습니다. Isolated Storage.

컨트롤 상태를 XML 또는 다른 형식으로 serialize 한 다음 (특히 WPF를 사용하여 종속성 속성을 저장하는 경우) 쉽게 파일을 사용자의 격리 된 저장소에 저장합니다.

앱 설정 경로를 가고 싶다면 나 자신도 한 번에 비슷한 것을 시도해 보았습니다 ... 아래의 접근 방식은 고립 된 저장소를 쉽게 사용할 수 있습니다.

class SettingsManager
{
    public static void LoadSettings(FrameworkElement sender, Dictionary<FrameworkElement, DependencyProperty> savedElements)
    {
        EnsureProperties(sender, savedElements);
        foreach (FrameworkElement element in savedElements.Keys)
        {
            try
            {
                element.SetValue(savedElements[element], Properties.Settings.Default[sender.Name + "." + element.Name]);
            }
            catch (Exception ex) { }
        }
    }

    public static void SaveSettings(FrameworkElement sender, Dictionary<FrameworkElement, DependencyProperty> savedElements)
    {
        EnsureProperties(sender, savedElements);
        foreach (FrameworkElement element in savedElements.Keys)
        {
            Properties.Settings.Default[sender.Name + "." + element.Name] = element.GetValue(savedElements[element]);
        }
        Properties.Settings.Default.Save();
    }

    public static void EnsureProperties(FrameworkElement sender, Dictionary<FrameworkElement, DependencyProperty> savedElements)
    {
        foreach (FrameworkElement element in savedElements.Keys)
        {
            bool hasProperty =
                Properties.Settings.Default.Properties[sender.Name + "." + element.Name] != null;

            if (!hasProperty)
            {
                SettingsAttributeDictionary attributes = new SettingsAttributeDictionary();
                UserScopedSettingAttribute attribute = new UserScopedSettingAttribute();
                attributes.Add(attribute.GetType(), attribute);

                SettingsProperty property = new SettingsProperty(sender.Name + "." + element.Name,
                    savedElements[element].DefaultMetadata.DefaultValue.GetType(), Properties.Settings.Default.Providers["LocalFileSettingsProvider"], false, null, SettingsSerializeAs.String, attributes, true, true);
                Properties.Settings.Default.Properties.Add(property);
            }
        }
        Properties.Settings.Default.Reload();
    }
}

.....과....

  Dictionary<FrameworkElement, DependencyProperty> savedElements = new Dictionary<FrameworkElement, DependencyProperty>();

public Window_Load(object sender, EventArgs e) {
           savedElements.Add(firstNameText, TextBox.TextProperty);
                savedElements.Add(lastNameText, TextBox.TextProperty);

            SettingsManager.LoadSettings(this, savedElements);
}

private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            SettingsManager.SaveSettings(this, savedElements);
        }



내 경험에 의하면 데이터베이스 테이블의 모든 설정을 저장하는 것이 가장 좋은 방법입니다. 성능에 대해 걱정하지 마십시오. 오늘날의 데이터베이스는 빠르고 테이블에 수천 개의 열을 쉽게 저장할 수 있습니다. 나는 이것을 힘든 방법으로 배웠습니다 - 제가 항복 / 탈 직렬화되기 전에 - 악몽이었습니다. 로컬 파일이나 레지스트리에 저장하는 것은 큰 문제가 있습니다. 앱을 지원해야하고 컴퓨터가 꺼져있는 경우 사용자가 앞에 있지 않습니다. 설정이 DB에있는 경우 수행 할 수있는 작업이 없습니다. 당신이 설정을 비교할 수 있다고 언급하지 않기 위해 그들과 비올라를 변경 ....




  1. 내가 일한 모든 곳에서 응용 프로그램 지원 때문에 데이터베이스가 필수적이었습니다. Adam의 말처럼 사용자가 책상에 앉아 있지 않거나 컴퓨터가 꺼져 있거나 다른 사람의 구성을 신속하게 변경하거나 새 대화 상대에게 기본 (또는 팀 구성원) 구성을 할당 할 수 있습니다.

  2. 응용 프로그램의 새 버전이 릴리스 될 때 설정이 증가 할 가능성이있는 경우 데이터를 모양으로 저장하여 응용 프로그램에서 직렬화 할 수 있습니다. 모듈이 반환 할 설정을 알 수 없으므로 모듈을 검색하는 Prism과 같은 것을 사용하는 경우 특히 유용합니다. blob은 사용자 이름 / 기계 복합 키에 의해 입력 될 수 있습니다. 그렇게하면 모든 컴퓨터에 대해 다른 설정을 할 수 있습니다.

  3. 내가 내장 된 설정 클래스를 많이 사용하지 않았으므로 주석을 쓰지 않을 것입니다. :)