在WPF中保存DataContext中的信息

时间:2014-06-29 11:17:44

标签: wpf datacontext

我想保存DataContext"值"目前我按下"保存设置"用户界面中的按钮,但我真的不知道该怎么做。我从XML文件中读取了几个设置,然后将它们绑定到不同的控件。阅读一些教程我实现了" INotifyPropertyChanged"接口(我也不知道究竟是什么)对于" GlobalSettings" class(我从我的xml文档中获取信息的地方)。

我不知道自己是否解释得很好,所以这里是代码......:

XAML控件:

            <GroupBox Grid.Row="0" Header="Multithreading related">
                <CheckBox Content="Use Multithreading" IsEnabled="False" VerticalAlignment="Center" Margin="5,0,0,0"/>
            </GroupBox>
            <GroupBox Grid.Row="1" Header="Search level related">
                <StackPanel Orientation="Horizontal" VerticalAlignment="Center">
                    <Label Content="Select the desired search level:" />
                    <ComboBox Width="200" Text="{Binding ProfileSelected}" x:Name="SearchLevelComboBox">
                        <ComboBoxItem>low</ComboBoxItem>
                        <ComboBoxItem>medium</ComboBoxItem>
                        <ComboBoxItem>high</ComboBoxItem>
                    </ComboBox>
                </StackPanel>
            </GroupBox>
            <GroupBox Grid.Row="2" Header="Profiles related">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition />
                        <RowDefinition />
                    </Grid.RowDefinitions>
                    <CheckBox x:Name="UseProfilesCheckbox" IsChecked="{Binding UseProfiles}"
                        Grid.Row="0" Content="Use profiles system" VerticalAlignment="Center" Margin="5,0,0,0"/>
                    <StackPanel Grid.Row="1" Orientation="Horizontal" VerticalAlignment="Center">
                        <Label Content="Select the profile you want to edit:" />
                        <ComboBox x:Name="ProfilesComboBox" 
                            Width="200">
                            <!-- Se llena dinamicamente -->
                        </ComboBox>
                    </StackPanel>
                </Grid>
            </GroupBox>
            <GroupBox Grid.Row="3" Header="General settings">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition />
                        <RowDefinition />
                    </Grid.RowDefinitions>
                    <StackPanel Grid.Row="0" VerticalAlignment="Center" Orientation="Horizontal">
                        <Label Content="Select 'Bots' directory:" />
                        <TextBox Width="350" Margin="10,0,0,0" Text="{Binding DefaultPath}"/>
                        <Button Content="Select..." Margin="10,0,0,0" Padding="5" Width="75"/>
                    </StackPanel>
                    <StackPanel Grid.Row="1" VerticalAlignment="Center" Orientation="Horizontal">
                        <Label Content="Username:" />
                        <!-- Binding username to settings -->
                        <TextBox Width="150" Text="{Binding Username}" />
                        <Label Content="(*) Should be the same as your forum username" />
                    </StackPanel>
                </Grid>
            </GroupBox>

GlobalSettings类:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using System.IO;
using System.Xml;
using System.ComponentModel;

namespace SmartGUI.Settings
{
    public class GlobalSettings : INotifyPropertyChanged
    {
        private bool _useMultithreading;
        private string _searchLevel;
        private bool _useProfiles;
        private string _profileSelected;
        private string _defaultPath;
        private string _username;
        public event PropertyChangedEventHandler PropertyChanged;

        public bool UseMultithreading
        {
            get
            {
                return _useMultithreading;
            }
            set
            {
                _useMultithreading = value;
                OnPropertyChanged("UseMultithreading");
            }
        }
        public string SearchLevel
        {
            get
            {
                return _searchLevel;
            }
            set
            {
                _searchLevel = value;
                OnPropertyChanged("SearchLevel");
            }
        }
        public bool UseProfiles
        {
            get
            {
                return _useProfiles;
            }
            set
            {
                _useProfiles = value;
                OnPropertyChanged("UseProfiles");
            }
        }
        public string ProfileSelected
        {
            get 
            {
                return _profileSelected;
            }
            set
            {
                _profileSelected = value;
                OnPropertyChanged("ProfileSelected");
            }
        }
        public string DefaultPath
        {
            get
            {
                return _defaultPath;
            }
            set
            {
                _defaultPath = value;
                OnPropertyChanged("DefaultPath");
            }
        }
        public string Username
        {
            get
            {
                return _username;
            }
            set
            {
                _username = value;
                OnPropertyChanged("Username");
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="path">The path you will load the settings from (NOT IMPLEMENTED)</param>
        /// <returns></returns>
        public static GlobalSettings Load(string path = null)
        {
            var settings = new GlobalSettings();

            try
            {
                if (!File.Exists("config.xml"))
                {
                    // Changed the simple linq way to save xml documents to this horrible thing just because
                    // xml.linq doesn't allow to omit the enconding line in the document 

                    var xmlConfig = new XElement("Settings");
                    xmlConfig.Add(new XElement("Multithreading", "false"));
                    xmlConfig.Add(new XElement("Searchlevel", "medium"));
                    xmlConfig.Add(new XElement("UseProfiles", "true"));
                    xmlConfig.Add(new XElement("CurrentProfile", "Defaut"));
                    xmlConfig.Add(new XElement("BotPath", ""));
                    xmlConfig.Add(new XElement("Username", "Unknown"));

                    var xmlSettings = new XmlWriterSettings { OmitXmlDeclaration = true, Indent = true };

                    using (XmlWriter xmlOutFile = XmlWriter.Create("config.xml", xmlSettings))
                    {
                        xmlConfig.Save(xmlOutFile);
                    }
                }

                XElement root = XElement.Load("config.xml");

                settings.UseMultithreading = Convert.ToBoolean(root.Element("Multithreading").Value);
                settings.SearchLevel = root.Element("Searchlevel").Value;
                settings.UseProfiles = Convert.ToBoolean(root.Element("UseProfiles").Value);
                settings.ProfileSelected = root.Element("CurrentProfile").Value;
                settings.DefaultPath = root.Element("BotPath").Value;
                settings.Username = root.Element("Username").Value;
            }
            catch (Exception ex)
            {
                //Show error maybe
                throw ex;
            }

            return settings;
        }

        public GlobalSettings()
        {

        }

        public void Save()
        {
            try
            {
                var root = new XElement("Settings");
                root.Add(new XElement("Multithreading", UseMultithreading));
                root.Add(new XElement("Searchlevel", SearchLevel));
                root.Add(new XElement("UseProfiles", UseProfiles));
                root.Add(new XElement("CurrentProfile", ProfileSelected));
                root.Add(new XElement("BotPath", DefaultPath));
                root.Add(new XElement("Username", Username));

                var xmlSettings = new XmlWriterSettings { OmitXmlDeclaration = true, Indent = true };

                using (XmlWriter xmlOutFile = XmlWriter.Create("config.xml", xmlSettings))
                {
                    root.Save(xmlOutFile);
                }
            }
            catch (Exception ex)
            {
                //Show error maybe
                throw ex;
            }
        }

        protected void OnPropertyChanged(string name)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(name));
            }
        }

    }
}

然后在MainWindow.xaml中我有:

private SmartGUI.Settings.GlobalSettings settings;
public MainWindow()
{
    InitializeComponent();
    settings = SmartGUI.Settings.GlobalSettings.Load();
    DataContext = settings;
}

所有这些评论都是因为我不是唯一一个使用该解决方案的人,所以我评论所有内容以帮助我的伙伴们理解。

如您所见,我可以在第一次加载窗口时设置控件的值,但现在我想将datacontext保存到xml设置文件中。

我认为用当前控件值替换config.xml可能是一个肮脏的解决方案,但肯定有更好的解决方案。

提前致谢。

2 个答案:

答案 0 :(得分:0)

嗯,首先,INotifyPropertyChanged用于绑定。因此,如果将XAML上的属性绑定到ViewModel上的属性,然后该属性发生更改,它将触发一个事件,该事件最终会使View使用正确的值更新GUI。没有它,除非您重新加载代码,否则您将无法看到更改。

关于保存设置:

右键点击您的项目,然后选择Add -> new item -> Settings File. 现在,您可以在该文件中拥有所有类型的默认值。 您可以从文件中加载它们,将它们保存到文件中,并恢复默认值,因此它非常方便。 这里有一些代码可以向您展示如何使用它:

// Lets assume you want to save this
string something_to_save = "Remember for next run";

// Assuming you called your setting files: AppSetting.settings
// and that you have a string property called: some_property_you_defined
AppSettings.Default.some_property_you_defined = something_to_save;

// Run this to save the changes
AppSettings.Default.Save();

// Now, close the app, open the app, and then:
string this_is_awesome = AppSettings.Default.some_property_you_defined;

// it should have the value you saved.

答案 1 :(得分:0)

我已经完成了保存DataContext的工作。您只需从Button Click处理程序中调用save方法,如:

    private void Save_OnClick(object sender, RoutedEventArgs e)
    {
           settings.Save();
    }

如果您不想在代码隐藏文件中处理Click事件。您可以使用WPF命令在GlobalSettings类本身上调用Save方法。

您可以从以下位置获取我创建的代码... http://1drv.ms/1q5rqlx