WPF: Como guardar definições usando uma classe

Neste artigo vamos criar uma classe para ler e guardar definições no ficheiro de definições por omissão.

Editar o ficheiro de definições

Quando criam uma aplicação WPF no Visual Studio é criado um ficheiro de definições automaticamente:

Ficheiro de definições
Ficheiro de definições

Podem abrir e editar o ficheiro usando o designer. Isto permite-vos criar as propriedades que querem ter nas definições, mas rapidamente podem perder o controlo se apenas usarem tipos simples numa estrutura unidimensional.

Acho muito mais útil encapsular as definições na minha própria estrutura de classes.

Criem a vossa própria classe de definições

Como exemplo, vamos criar uma classe para guardar o estado de uma janela.

[Serializable]
public class WindowConfig
{
    public int Height { get; set; }
    public int Width { get; set; }
    public int Left { get; set; }
    public int Top { get; set; }
    public WindowState WindowState { get; set; }
    
    public WindowConfig()
    {
    }
}

Se calhar também querem que a vossa aplicação suporte temas:

public enum Theme
{
    Light,
    Dark,
    Blue
}

A nossa classe principal ficaria então assim:

[Serializable]
public class MyConfig
{
    public WindowConfig MainWindow { get; set; }
    public Theme Theme { get; set; }
    
    public MyConfig()
    {
        MainWindow = new WindowConfig();
        MainWindow.Width = 600;
        MainWindow.Height = 400;
  
        Theme = Theme.Light;
    }
}

Para isto funcionar todas as classes têm de ser serializable e ter um constructor vazio. Costumo colocar as definições por omissão no constructor principal.

Adicionem o vosso tipo às definições

O próximo passo é criar uma nova propriedade no ficheiro das definições com o tipo apropriado:

Definições - procurar tipo
Definições - procurar tipo

Nota: o designer não mostra tipos da sua própria assembly. Têm duas opções: ou mantêm as vossas classes de definições numa assembly separada ou então escrevem manualmente o nome completo do tipo que querem na caixa de texto.

Inicializar as definições no startup

A primeira vez que correm a aplicação, o objecto vai estar nulo, por isso têm de se certificar que é criado:

protected override void OnStartup(StartupEventArgs e)
{
    base.OnStartup(e);
    
    if (Settings.Default.Config == null)
    {
        Settings.Default.Config = new MyConfig();
    }
}

Como podem reparar, podem aceder às definições em qualquer parte da aplicação usando a propriedade Settings.Default.Config. Não só podem ler os valores como também actualizá-los.

Se quiserem guardar as definições chamem o método Settings.Default.Save();.

Liguem as definições às vossas views

Vamos agora dar uso às definições. Vamos criar uma extensão que nos permite facilmente ligar uma propriedade de um controlo a um valor nas definições.

public class SettingBindingExtension : Binding
{
    public SettingBindingExtension()
    {
        Initialize();
    }
    
    public SettingBindingExtension(string path)
        : base(path)
    {
        Initialize();
    }
    
    private void Initialize()
    {
        this.Source = Settings.Default.Config;
        this.Mode = BindingMode.TwoWay;
    }
}

E na view ligamos as definições assim:

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:my="clr-namespace:WpfApplication1"
    Title="MainWindow"
    Width="{my:SettingBinding MainWindow.Width}"
    Height="{my:SettingBinding MainWindow.Height}"
    Top="{my:SettingBinding MainWindow.Top}"
    Left="{my:SettingBinding MainWindow.Left}"
    WindowState="{my:SettingBinding MainWindow.WindowState}" />

Guardar ao sair

Podem guardar as definições sempre que a aplicação é fechada com o seguinte código:

protected override void OnExit(ExitEventArgs e)
{
    base.OnExit(e);
    Settings.Default.Save();
}
Nuno Freitas
Publicado por Nuno Freitas em 24 março, 2014

Artigos relacionados