【问题标题】:Saving information from DataContext in WPF在 WPF 中保存来自 DataContext 的信息
【发布时间】:2014-06-29 11:17:44
【问题描述】:

当我按下 UI 中的“保存设置”按钮时,我想保存 DataContext“值”,但我真的不知道该怎么做。我从 XML 文件中读取了一些设置,然后将它们绑定到不同的控件。阅读一些教程,我实现了“INotifyPropertyChanged”接口(我也不知道究竟是做什么的)到“GlobalSettings”类(这是我从我的 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>

全局设置类:

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;
}

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

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

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

提前致谢。

【问题讨论】:

    标签: wpf datacontext


    【解决方案1】:

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

    关于保存设置:

    右键单击您的项目,然后选择Add -&gt; new item -&gt; 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.
    

    【讨论】:

    • 感谢 INotifyPropertyChanged 的​​解释,但使用 %AppData% 设置不是我在做的,我曾经使用它进行管理,但切换到自定义 xml 文件。
    • 所以您只想将上下文添加到您的设置中?
    • 我想在按下“保存设置”按钮时保存当前的DataContext,问题是你不能有像“DataContext.SelectedProfile”这样的东西,因为它继承自窗口中的设置构造函数...
    【解决方案2】:

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

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多