Avatar billede poul10 Nybegynder
19. maj 2011 - 13:12 Der er 5 kommentarer og
1 løsning

IsDirty implementation

Hej alle,
Jeg sidder og roder med nogle windows forms og leder efter en god måde at håndtere "Save Changes Yes/No/Cancel" når man har lavet ændringer på brugergrænsefladen.

Mit umiddelbare bud var at lave en ekstra property på mine objekter som hedder "IsDirty" og så sætte den når jeg retter forskellige steder:

Eksempel:
Jeg har et Bil objekt som jeg læser ud i nogle tekstboxe i min form. Når jeg så retter f.eks. navnet ville jeg gå ind under textchanged eventen på den textbox og sætte Bil.IsDirty = True, og så tjekke på denne "IsDirty" property når jeg prøver at lukke programmet eller gør andet som kræver der bliver gemt.

Jeg ved ikke om det er den bedste måde, det virker "lidt for simpelt". Jeg er stor fan af at gøre det så simpelt som muligt men er dette en holdbar måde at gøre det på?
Avatar billede oneeighty Nybegynder
19. maj 2011 - 18:42 #1
En simpel løsning kunne være at implementere INotifyPropertyChanged og subscribe på eventet i constructoren.I handler-metoden sættes IsDirty til true. Dog mangler der håndtering af situationer hvor der først ændres en værdi i en property og derefter ændres tilbage til samme værdi som oprindeligt
Avatar billede poul10 Nybegynder
20. maj 2011 - 00:21 #2
Hej oneeighty, tak for tippet.
Jeg er ikke skide skarp til det med events men jeg har skrevet følgende: (sig endelig til hvis det kan blive endnu mere simpelt)

public partial class Form1 : Form
    {
        DemoCustomer dc;

        public Form1()
        {
            InitializeComponent();
            dc = new DemoCustomer();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            richTextBox1.Text += dc.IsDirty.ToString();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            dc.Name = "Lars";
            dc.Age = "123";
        }
    }

    public class DemoCustomer : INotifyPropertyChanged
    {
        private string _name;
        private string _age;
        private bool _isDirty;
        public event PropertyChangedEventHandler PropertyChanged;

        public bool IsDirty
        {
            get { return _isDirty; }
            set { _isDirty = value; }
        }

        public string Name
        {
            get { return _name; }
            set { _name = value; NotifyPropertyChanged("Name"); }
        }

        public string Age
        {
            get { return _age; }
            set { _age = value; NotifyPropertyChanged("Age"); }
        }

        public DemoCustomer()
        {
            this.PropertyChanged += new PropertyChangedEventHandler(DemoCustomer_PropertyChanged);
        }

        void DemoCustomer_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            _isDirty = true;
        }

        private void NotifyPropertyChanged(string field)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(field));
            }
        }
    }
Avatar billede arne_v Ekspert
23. maj 2011 - 02:05 #3
Jeg kan ikke rigtigt se hvad INotifyPropertyChanged hjaelper. Det er en metode hvormed andre objekter kan subscribe paa aendringer i dette objekt. Men dette objekt skal selv kalde i alle setters. Det er nemmere at bare saette dirty til true i alle setters.
Avatar billede arne_v Ekspert
23. maj 2011 - 03:35 #4
Jeg tror at den fornuftige loesning er selv at saette det dirty flag i all setters.

Hvis:
1) du har hang til avanceret kode
2) du har mulighed for at erklaere alle properties virtual

Saa kan du lege lidt med Castle DynamicProxy:


using System;

using Castle.Core;
using Castle.DynamicProxy;

namespace E
{
    public interface IDirty
    {
        bool Dirty { get; set; }
    }
    public class Data : IDirty
    {
        public virtual int Iv { get; set; }
        public virtual string Sv { get; set; }
        public bool Dirty { get; set; }
    }
    public static class DirtyWrapper
    {
        internal class DirtyWrapperInterceptor : IInterceptor
        {
            public void Intercept(IInvocation inv)
            {
                if(inv.Method.IsSpecialName && inv.Method.Name.StartsWith("set_"))
                {
                    ((IDirty)inv.Proxy).Dirty = true;
                }
                inv.Proceed();
            }
        }
        public static T DirtyWrap<T>(this ProxyGenerator gen, T o) where T : class
        {
            return gen.CreateClassProxyWithTarget(o, new IInterceptor[] { new DirtyWrapperInterceptor() });
        }
    }
    public class Program
    {
        public static void Main(string[] args)
        {
            ProxyGenerator gen = new ProxyGenerator();
            // change base object
            Data o = new Data();
            Console.WriteLine(o.Iv + " " + o.Sv + " " + o.Dirty);
            o.Iv = 123;
            o.Sv = "ABC";
            Console.WriteLine(o.Iv + " " + o.Sv + " " + o.Dirty);
            // change wrapped object
            Data o2 = new Data();
            Console.WriteLine(o2.Iv + " " + o2.Sv + " " + o2.Dirty);
            o2 = gen.DirtyWrap(o);
            o2.Iv = 123;
            o2.Sv = "ABC";
            Console.WriteLine(o2.Iv + " " + o2.Sv + " " + o2.Dirty);
            //
            Console.ReadKey();
        }
    }
}
Avatar billede poul10 Nybegynder
26. maj 2011 - 14:27 #5
Hej med jer,
Beklager den lange svartid.
Jeg tror bare jeg lytter efter arne_v, han plejer at vide hvad han snakker om og det er også den klart mest simple løsning.

Hele ideen bag er jo egentligt bare at kunne spørge på objektet og se om der skal gemmes noget til databasen hvis man går væk fra skærmbilledet uden at gemme.

Smid et svar så får i nogle point, jeg blev trods alt lidt klogere på events :)
Avatar billede arne_v Ekspert
27. maj 2011 - 00:41 #6
svar
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester