Avatar billede Jim Rasmussen Novice
04. juli 2011 - 09:15 Der er 47 kommentarer og
1 løsning

DataBinding in wpf/c#

Jeg har en UserControl som henter data fra en xml fil. Brugeren kan så tilføje data til denne xml fil via en anden UserControl.

Mit spørgsmål er nu hvordan jeg beder den første UserControl om at opdatere sig i forehold til xml filen?
Avatar billede Jim Rasmussen Novice
04. juli 2011 - 11:06 #1
Altså kort fortalt "få en funktion til at køre når der sker ændringer i xml filen"
Avatar billede janus_007 Nybegynder
04. juli 2011 - 11:49 #2
Det kan du løse på flere måder:
Den nemme er smid instancen af UserControl 1 ind i UserControl 2 og
eksekver læsning.
Den gode er med events
Den fine er med delegates

Stigende i sværhedsgrad og kompleksitet :)

Vælg en og hør mere!
Avatar billede Jim Rasmussen Novice
04. juli 2011 - 11:58 #3
Jamen jeg vælger events så ;)
Avatar billede janus_007 Nybegynder
04. juli 2011 - 12:39 #4
Lad os kalde dem for ReadData og InputData.

I InputData opretter du en event:

public class InputData
{
  public event EventHandler DataChanged;

  public UserChangesSomeDataFoo()
  {

  }
  public void OnDataChanged()
  {
    if(this.InputData != null) //her chekkes om nogle subscriber til den, hvis man rejser en event uden dette check og der ikke findes nogen subscriber vil det give en null exception
    this.InputData(this, EventArgs.Empty);  // det her er totalt basic.. du kan uden videre også medsende argumenter til subscriberen, men vi holder det simpelt lige pt :)
  }
  ...
  ...
 
}

Din ReadData må nødvendigvis have en metode du kan trigge for at læse indholdet i Xml'en...

public class ReadData
{
  public ReadXml()
  {
    //do something...
  }
}

UserControls har i sagens natur en Main, hvor der er tilknyttet.
I Main instancierer du:

class Main
{
  var usrCtrlInput = new InputData();

  //til denne findes der nu en event:
  usrCtrlInput.DataChanged += InputDataChanged;

  void InputDataChanged(object sender, EventArgs e)
  {
    var readData = new ReadData()
    readData.ReadXml();
  }
}
Avatar billede Jim Rasmussen Novice
04. juli 2011 - 13:37 #5
if(this.InputData != null)

Får en fejl ved det her? (:
Avatar billede Syska Mester
04. juli 2011 - 15:21 #6
Det er nok "DataChanged" han vil tjekke om ikke er null

if(DataChanged != null)
Avatar billede Jim Rasmussen Novice
04. juli 2011 - 17:12 #7
usrCtrlInput.DataChanged += InputDataChanged;

HEr skal InputDataChanged da have to paremetre? sender og e?

Hvad skal de indeholde?
Avatar billede Syska Mester
04. juli 2011 - 17:20 #8
sender skal vel være sender, altså hvilket object der forsagede eventen ... og det andet argumenter, som her er af: http://msdn.microsoft.com/en-us/library/system.eventhandler.aspx

Janus har i hans eksemple sendt:
http://msdn.microsoft.com/en-us/library/system.eventargs.aspx
EventArgs.Empty <- med ... læs om den i overstående link.

Kaldet kommer så til at se således ud:
if(DataChanged != null)
    this.DataChanged(this, EventArgs.Empty);
Avatar billede Jim Rasmussen Novice
04. juli 2011 - 20:04 #9
Kan ikke få det til at virke :s

Prøver at finde en anden metode at gøre det på så.

Jeg er vandt til at bruge postbacks til at gøre den her slags ting når jeg laver hjemmesider, eller ajax.

Men tak for hjælpen (:
Avatar billede Syska Mester
04. juli 2011 - 20:24 #10
Få hvad til hvad virke? Hvad virker ikke? Jeg ville gerne kunne læse dine tanker ... men det kan jeg desværre ikke.

Er det compile fejl?
Runtime ?
Hvad er fejlen ?

"Få det til at virke er meget abstrakt"

Som en på twitter skrev i dag:
@maartenballiauw: If you log a bug, give me info! Not just "Its not working". Waste of my time, waste of your time.
Avatar billede janus_007 Nybegynder
04. juli 2011 - 20:46 #11
Hej DSDM

Tak buzzzz for dine indlæg, det er naturligvis DataChanged som skal chekkes for null.

DSDM, UserChangesSomeDataFoo(), skal du kalde OnDataChanged for at trigge eventen.

Prøv det og jeg kan garantere at det virker :)
Avatar billede Jim Rasmussen Novice
05. juli 2011 - 10:33 #12
Sorry buzzzz. VAr træt og gad ikke at bøvle mere (:


Her er hvad der ligger i den control som læser fra xml filen

    public class InputData
    {
      public event EventHandler DataChanged;

      public void OnDataChanged()
      {
        if(this.DataChanged != null)
        this.DataChanged(this, EventArgs.Empty);
      }

    }

    public class ReadData
    {
      public void ReadXml()
      {
          ManageCodes mc = new ManageCodes();
          mc.loadXml();
      }
    }

Yderligere har jeg dette i den som skal tilføje til filen

var usrCtrlInput = new InputData();

usrCtrlInput.DataChanged += InputDataChanged;

void InputDataChanged(object sender, EventArgs e)
{
    var readData = new ReadData();
    readData.ReadXml();
}



Linien som er markeret med fed giver en compile fejl. "} expected"
Avatar billede Jim Rasmussen Novice
05. juli 2011 - 13:00 #13
hoc. Det er linien under der giver fejlen. (;
Avatar billede Jim Rasmussen Novice
05. juli 2011 - 13:40 #14
HAr fået compiler fejlen rettet nu!

Havde sat denne inden i en anden event
void InputDataChanged(object sender, EventArgs e)
{
    var readData = new ReadData();
    readData.ReadXml();
}

:p


Men det fungere bare stadig ikke!?

Når jeg via den kontrol som skal læse xml filen åbner den kontrol der skal tilføje til xml filen, så burde kontrollen der læser xml filen jo nu opdatere sig? Men det gør den først hvis jeg lukke programmet og åbner det igen :(
Avatar billede janus_007 Nybegynder
05. juli 2011 - 17:47 #15
Hej DSDM

Når der ændres i Xml-filen gemmer du så dette til disk? eller hvordan?
Avatar billede Jim Rasmussen Novice
05. juli 2011 - 20:03 #16
Jeg bruger nedenfor kode til at tilføje til min xml fil

XDocument doc = XDocument.Load(xmlFile);

                doc.Root.Add(new XElement("Entry",
                    new XAttribute("id", DateTime.Now.ToString().Replace("-", "").Replace(":", "").Replace(";", "").Replace(" ", "")),
                    new XElement("Date", pro.dateSubmitted),
                    new XElement("Name", pro.Name),
                    new XElement("Description", pro.Description),
                    new XElement("Website", pro.website),
                    new XElement("Content", pro.Content)
                    )
                );

                doc.Save(xmlFile);
Avatar billede janus_007 Nybegynder
05. juli 2011 - 21:09 #17
aha... og efter .Save rejser du eventen DataChanged ? er det korrekt?
Avatar billede Jim Rasmussen Novice
05. juli 2011 - 22:15 #18
jo det er rigtigt (: Er det da et problem?

Forresten. hvorfor skulle lave nedenstående?

public UserChangesSomeDataFoo()
  {

  }
  public void OnDataChanged()
  {
    if(this.InputData != null) //her chekkes om nogle subscriber til den, hvis man rejser en event uden dette check og der ikke findes nogen subscriber vil det give en null exception
    this.InputData(this, EventArgs.Empty);  // det her er totalt basic.. du kan uden videre også medsende argumenter til subscriberen, men vi holder det simpelt lige pt :)
  }


Er det ikke nok med OnDataChanged?
Avatar billede janus_007 Nybegynder
05. juli 2011 - 22:41 #19
Hej DSDM

Jo jo.. ..Foo er bare for at vise en metode, vidste ikke hvad du kaldte den :)

Kan godt se fejlen her... jeg fik måske skrevet for hurtigt sidst.

Der skal stå:
public void OnDataChanged()
  {
    if(this.DataChanged != null)
    this.DataChanged(this, EventArgs.Empty); 
  }

Og så kalder du OnDataChanged efter doc.Save(xmlFile);

Jeg troede ovenstående var rettet en gang?

Sæt et breakpoint i .
void InputDataChanged(object sender, EventArgs e)
{
    var readData = new ReadData();
    readData.ReadXml();
}
Og se om den bliver trigget korrekt :)
Avatar billede Jim Rasmussen Novice
05. juli 2011 - 23:57 #20
mener du sådan her?
void InputDataChanged(object sender, EventArgs e)
{
    var readData = new ReadData();
    readData.ReadXml();
    break;
}

For det kan jeg ikke (: Den siger at "No closing loop out of which to  break"



Bare lige for at være sikker.
Er det rigtigt forstået at jeg skal bruge denne

usrCtrlInput.DataChanged += InputDataChanged;

og denne

void InputDataChanged(object sender, EventArgs e)
        {
            var mc = new ManageCodes();
            mc.loadXml();
        }

I den kontrol som tilføjer til filen

og så event handleren samt OnDataChanged i den kontrol der læser fra xml filen ? (:
Avatar billede Jim Rasmussen Novice
06. juli 2011 - 00:04 #21
Det er sjovt. For jeg har prøvet at fjerne alt det som sker i den event der tilføjer til xml filen og bare skjule en kontrol i den user control som åbner denne kontrol. Men uanset hvad så, sker ændringerne først når jeg lukker den første kontrol og åbner den igen

Det er ikke forkert at jeg bruger en user coltrol til at åbne en anden med vel?
Avatar billede Syska Mester
06. juli 2011 - 00:05 #22
break point, så du kan se om du komemr ind i den method når de køre din application med en debugger attached. ( ved at trykke F5 )

Jeg er ved at være lidt lost i alt det løse kode, så tror janus_007 har et lidt bedre overblik :-)

mvh
Avatar billede Jim Rasmussen Novice
06. juli 2011 - 00:23 #23
Arh, Sådan en break. Ja god idé :p Tak buzzzz. Forståeligt (:
Avatar billede Jim Rasmussen Novice
06. juli 2011 - 00:54 #24
Her er hele den side der tilføjer til xml filen

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using xmlConnect;

namespace Pages
{
    /// <summary>
    /// Interaction logic for submit.xaml
    /// </summary>
    public partial class submit : UserControl
    {
        public submit()
        {
            InitializeComponent();
        }

        private void btnClose_Click(object sender, RoutedEventArgs e)
        {
            ((StackPanel)this.Parent).Children.Remove(this);
        }

        private void btnSubmit_Click(object sender, RoutedEventArgs e)
        {
            codeFactory code = new codeFactory();
            codeProperty pro = new codeProperty();
            errorPro proError = new errorPro();

            pro.Content = txtContent.Text;
            pro.dateSubmitted = DateTime.Now.ToShortDateString();
            pro.Description = txtDescription.Text;
            pro.Name = txtName.Text;
            pro.website = txtWebsite.Text;

            proError = code.addEntry(pro, "user.xml");

            if (proError.goodOrBad == 1)
            {
                var usrCtrlInput = new ManageCodes();
                usrCtrlInput.DataChanged += InputDataChanged;

                ((StackPanel)this.Parent).Children.Remove(this);
            }
        }

        void InputDataChanged(object sender, EventArgs e)
        {
            var mc = new ManageCodes();
            mc.loadXml();
        }
    }
}
Linien med fed er hvor den tilføjer til xml filen

Og et break point ud for void InputDataChanged fanger intet?

Og har husked debug
Avatar billede janus_007 Nybegynder
06. juli 2011 - 19:31 #25
Ok.. nu ser jeg det.

Den usercontrol du har der, den må også eksistere med en mainform korrekt? Hvad hedder den?

Den kode du har bikset sammen der svarer lidt mere til den du sagde du ikke ville ha :), altså mulighed 1, du ville have mulighed 2 og den bygger på en mainform hvori du placerer dine usercontrols, så hvad hedder din mainform? Og hvor placerer du dine usercontrols?

ManageCodes er en usercontrol, korrekt? som ligger på samme mainform som den submit-form du har postet der, korrekt?

Som jeg ser det instancierer du ManageCodes flere gange nu kender jeg ikke til funktionaliteten i ManageCodes, men umiddelbart er det heri fejlen ligger.
Avatar billede janus_007 Nybegynder
06. juli 2011 - 19:42 #26
Du skal have et pattern lidt alá.. lidt pseudocode her:

class MainForm

{
//add usercontrols

var usrControlSubmit = new submit();
panel1.Add(usrControlSubmit);

var usrManageCodes = new ManageCodes();
panel2.Add(usrManageCodes)

usrControlSubmit.DataChanged += InputDataChanged;

  void InputDataChanged()
  {
    usrManageCodes.loadxml();
  }
}

Du skal ikke instanciere ManageCodes inde fra din submitcontrol :), men altså forbinde det hele fra din Main.... er du med?
Avatar billede Jim Rasmussen Novice
06. juli 2011 - 19:56 #27
-------------------//Main//--------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using xmlConnect;
using Pages;
using System.IO;
using System.Windows.Media.Animation;

namespace CodeKeeber
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            if (File.Exists("user.xml"))
            {
                lblLoginHead.Content = "Login";
            }
            else
            {
                lblLoginHead.Content = "First time login";
                btnLogin.Content = "Create user";
            }

            //Edit profile
            btnProfile.Visibility = System.Windows.Visibility.Hidden;
            //----------//
        }

        private void btnLogin_Click(object sender, RoutedEventArgs e)
        {
            errorPro error = new errorPro();

            loginFactory login = new loginFactory();

            if (File.Exists("user.xml"))
            {
                error = login.login(txtPassword.Text, txtUsername.Text, "user.xml");

                if (error.goodOrBad == 1)
                {
                    if (error.loggedIn == 1)
                    {
                        pnlLogin.Visibility = System.Windows.Visibility.Hidden;
                        btnProfile.Visibility = System.Windows.Visibility.Visible;
                        stBarUserInformation.Content = "Login success";

                        rctLogo.Margin = new Thickness(5, 25, 5, 5);

                        ManageCodes mg = new ManageCodes();
                        pnlNewControls.Children.Add(mg);
                    }
                    else
                    {
                        lblLoginFeedback.Content = "login failed!";
                    }
                }
                else
                {
                    lblLoginFeedback.Content = error.shortMessage;
                }
            }
            else
            {
                error = login.insertNewLogin(txtPassword.Text, txtUsername.Text, "user.xml");

                if (error.goodOrBad == 1)
                {
                    pnlLogin.Visibility = System.Windows.Visibility.Hidden;
                    btnProfile.Visibility = System.Windows.Visibility.Visible;
                    stBarUserInformation.Content = "Login success";

                    rctLogo.Margin = new Thickness(5, 25, 5, 5);

                    ManageCodes mg = new ManageCodes();
                    pnlNewControls.Children.Add(mg);
                }
                else
                {
                    lblLoginFeedback.Content = error.shortMessage;
                }
            }
        }

        private void btnFile_Click(object sender, RoutedEventArgs e)
        {
            pnlNewControls.Children.Clear();
            pnlLogin.Visibility = Visibility.Visible;
            btnProfile.Visibility = Visibility.Hidden;
            btnLogout.Visibility = Visibility.Hidden;
            txtPassword.Text = null;
            txtUsername.Text = null;

            if (File.Exists("user.xml"))
            {
                lblLoginHead.Content = "Login";
            }
            else
            {
                lblLoginHead.Content = "First time login";
                btnLogin.Content = "Create user";
            }
        }
    }
}



-----------------------//ManageCodes//----------------------------

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using xmlConnect;
using System.IO;

namespace Pages
{
    /// <summary>
    /// Interaction logic for ManageCodes.xaml
    /// </summary>
    public partial class ManageCodes : UserControl
    {
        public ManageCodes()
        {
            InitializeComponent();

            loadXml();
        }

        private void btnAddCode_Click(object sender, RoutedEventArgs e)
        {
            submit sb = new submit();

            pnlListOfCodes.Children.Add(sb);
        }

        public void loadXml()
        {
            codeFactory objCode = new codeFactory();
            codeProperty objPro = new codeProperty();

            foreach (codeProperty pro in objCode.getAllCodes("user.xml"))
            {
                Border bd = new Border();
                bd.Height = 30;
                bd.Padding = new Thickness(5);
                bd.BorderBrush = Brushes.Black;
                bd.BorderThickness = new Thickness(1);
                bd.Background = Brushes.Silver;

                pnlListOfCodes.Children.Add(bd);
            }
        }

        public event EventHandler DataChanged;

        public void OnDataChanged()
        {
            if (this.DataChanged != null)
            {
                this.DataChanged(this, EventArgs.Empty);
            }
        }
    }
}



------------------------//Submit//--------------------

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using xmlConnect;

namespace Pages
{
    /// <summary>
    /// Interaction logic for submit.xaml
    /// </summary>
    public partial class submit : UserControl
    {
        public submit()
        {
            InitializeComponent();
        }

        private void btnClose_Click(object sender, RoutedEventArgs e)
        {
            ((StackPanel)this.Parent).Children.Remove(this);
        }

        private void btnSubmit_Click(object sender, RoutedEventArgs e)
        {
            codeFactory code = new codeFactory();
            codeProperty pro = new codeProperty();
            errorPro proError = new errorPro();

            pro.Content = txtContent.Text;
            pro.dateSubmitted = DateTime.Now.ToShortDateString();
            pro.Description = txtDescription.Text;
            pro.Name = txtName.Text;
            pro.website = txtWebsite.Text;

            proError = code.addEntry(pro, "user.xml");

            if (proError.goodOrBad == 1)
            {
                var usrCtrlInput = new ManageCodes();
                usrCtrlInput.DataChanged += InputDataChanged;

                ((StackPanel)this.Parent).Children.Remove(this);
            }
        }

        void InputDataChanged(object sender, EventArgs e)
        {
            var mc = new ManageCodes();
            mc.loadXml();
        }
    }
}



-----------------------------------------------------------

Min main ligger i et projekt for sig selv kaldet CodeKeeber

Submit og ManageCodes ligger i et andet projekt kaldet Pages

Når man er logget ind instanciere jeg ManageCodes i min Main og tilføjer den som en UserControl, som så læser min xml fil.
I min ManageCodes kan man så tilføje data til xml filen, der instanciere jeg så Submit og tilføjer den som en UserControl i min ManageCodes UserControl.

Altså når man så har tilføjet til min xml fil via User kontrollen Submit som instancieres i userkontroll ManageCodes, lukkes den igen af sig selv. Det er så her jeg vil have User kontrollen ManageCodes til at opdatere sig fra xml filen igen, så man kan se ændringerne. (: Men der sker INTET! ikke før jeg lukker min solution og starter den igen. Eller logger ud og ind igen (Altså fjerner mine user kontroller og tilføjer dem igen)
Avatar billede Jim Rasmussen Novice
06. juli 2011 - 20:08 #28
Men må man da ikke instanciere en usercontrol mere end en gang ?
Avatar billede janus_007 Nybegynder
06. juli 2011 - 21:29 #29
Hej DSDM

Du er tæt på :)

Det ser bare ud som om du har ombyttet publisher med subscriber.

I din submit-class fjerner du InputDataChanged og tilføjer:
public event EventHandler DataChanged;
public void OnDataChanged()
        {
            if (this.DataChanged != null)
            {
                this.DataChanged(this, EventArgs.Empty);
            }
        }

I class ManageCode
private void btnAddCode_Click(object sender, RoutedEventArgs e)
        {
            submit sb = new submit();
            sb.DataChanged += InputDataChanged();
            pnlListOfCodes.Children.Add(sb);
        }
og stadig i samme class, smider du metoden:
void InputDataChanged(object sender, EventArgs e)
        {
            this.loadXml();
        }
Avatar billede Jim Rasmussen Novice
06. juli 2011 - 22:33 #30
Det forstår jeg bare ikke? (: Det er jo her i denne metode jeg skal bede ManageCodes om at loade xml filen igen? (:

private void btnSubmit_Click(object sender, RoutedEventArgs e)
        {
            codeFactory code = new codeFactory();
            codeProperty pro = new codeProperty();
            errorPro proError = new errorPro();

            pro.Content = txtContent.Text;
            pro.dateSubmitted = DateTime.Now.ToShortDateString();
            pro.Description = txtDescription.Text;
            pro.Name = txtName.Text;
            pro.website = txtWebsite.Text;

            proError = code.addEntry(pro, "user.xml");

            if (proError.goodOrBad == 1)
            {
                Der er her jeg vil bede ManageCodes om at loade xml filen igen
                ((StackPanel)this.Parent).Children.Remove(this);
            }
        }

btnAddCode_Click er jo bare til at tilføje min Submit-class til min ManageCode-class
Avatar billede janus_007 Nybegynder
06. juli 2011 - 23:17 #31
Ahh ja du havde jo også denne: usrCtrlInput.DataChanged += InputDataChanged;


Udskift den med :
OnDataChanged();

der :)

OnDataChanged er en metode som jo ligger i din submit-class :), se min tidligere post.
Avatar billede janus_007 Nybegynder
06. juli 2011 - 23:22 #32
I virkeligheden kan man sige at du indirekte beder Managecode om at genindlæse filen, det du gør ved at rejse en event er at alle subscribere vil modtage information om at DataChanged :) , i dit tilfælde har du kun sat en subscriber på nemlig ManageCode så den vil naturligvis modtage publish-eventen :)

Lad os for sjov antage at du har en helt 3. Usercontrol som skal blinke i 3 sekunder når xml'en er ændret, denne 3. UserControl kan du så også opsætte og altså abonnere på events fra Submit-class. Det smarte i sådan et setup er at Submit-klassen ikke behøver vide noget om hvor informationen omkring xml er ændret bliver anvendt. Smart ik :)
Avatar billede janus_007 Nybegynder
06. juli 2011 - 23:32 #33
Du skal stadig beholde denne :

private void btnAddCode_Click(object sender, RoutedEventArgs e)
        {
            submit sb = new submit();
            sb.DataChanged += InputDataChanged();
            pnlListOfCodes.Children.Add(sb);
        }


Den fortæller din submit at der er en subscriber til eventen :)
Avatar billede Jim Rasmussen Novice
06. juli 2011 - 23:54 #34
IT WORKS!!!! :D TAK TAK TAK (:


Jeg forstår nu. Og jo det er da skide smart.


Altså det vil sige at faktisk er det min ManageCode-class der subscriper på den eventhandler der ligger i min submit.class?

I så fald så er det jo egentlig ret smart! (: For så kan jeg jo lade alt muligt andet subscripe til den eventhandler der ligger i min submit-class, uden som sådan at skulle tage hensyn til det i min submit-class
Avatar billede Jim Rasmussen Novice
06. juli 2011 - 23:55 #35
Kan jeg øge points her? For du har jo næsten sat mig ind i hvad det vil sige at bruge events :p
Avatar billede Jim Rasmussen Novice
06. juli 2011 - 23:57 #36
Hvis jeg nu skulle sende parametre med ud til mine subscribere? er det så i EventArgs det skal gøres? (:
Avatar billede Syska Mester
07. juli 2011 - 00:05 #37
Jeps ...

Det er sådan ButtonClick virker etc. i WPF hedder de RoutedEventArgs.

Arv fra EventArgs og lave din egen ... så kan du sende med præcis hvad du lyster.

mvh
Avatar billede janus_007 Nybegynder
07. juli 2011 - 00:22 #38
Godt du fik det løst og lærte noget nyt undervejs :)

Og jep.. som buzzzz skriver så skla du lave din egen klasse som nedarver fra EventArgs

public class SubmitEventArgs : EventArgs
{
public ... SomeProperty... {get; set;} osv....
}

og så :

public void OnDataChanged(string someValue)
        {
            if (this.DataChanged != null)
            {
                var e = new SubmitEventArgs();
                e.SomeProperty = someValue;
                this.DataChanged(this, e);
            }
        }

Mulighederne er mange, men ja... det er sådan :)
Avatar billede Jim Rasmussen Novice
07. juli 2011 - 00:49 #39
Hvordan skiller jeg så de forskellige parametre ad som befinder sig i e? :p Altså når en abonnent skal bruge dem
Avatar billede Syska Mester
07. juli 2011 - 00:54 #40
var property = e.SomeProperty;

Eller hvad mener du med "hvordan skiller sig dem ad" ?

Det er et jo næsten et almindeligt .NET Object, så alt efter hvordan du har konktrueret det, er det jo nemt.
Avatar billede Jim Rasmussen Novice
07. juli 2011 - 01:03 #41
void InputDataChanged(object sender, EventArgs e)
        {
            lblOutput.Content = e.noget;
        }

Ovenfor vil jeg bruge en property fra e

Men i stedet for "noget" kan jeg kun vælge Equals, GetHashCode, GetType eller ToString?


Eller gør jeg det forkert :p?
Avatar billede Syska Mester
07. juli 2011 - 01:12 #42
Har du lavet din egen eventargs som janus også har beskevet? Og du skal huske at ændre din signatur her også ...

Du modtager en EventArgs, men har måske lavet en anden ... nedarvet type.

da CustomEventArgs godt kan assignes til EventArgs tror jeg godt det kan lade sig gøre.

Men her er lidt kode:
public class ContentEventArgs : EventArgs
    {
        public string Content { get; set; }

        public ContentEventArgs(string content)
        {
            Content = content;
        }
    }


Og din eventhandler laver du om til:
void InputDataChanged(object sender, ContentEventArgs e)
        {
            lblOutput.Content = e.Content;
        }

mvh
Avatar billede Jim Rasmussen Novice
07. juli 2011 - 01:43 #43
void InputDataChanged(object sender, ContentEventArgs e)
        {
            lblOutput.Content = e.Content;
        }

Hvis jeg gør ovenstående får jeg en compilerfejl?

No overload for 'InputDataChanged' matches delegate 'System.EventHandler'


Fejlen kommer ikke hvis jeg bare 'EventArgs e'
Avatar billede Syska Mester
07. juli 2011 - 02:09 #44
Jeg er meget lidt opfindsom :-)

public class ContentEventArgs : EventArgs
    {
        public string Content { get; set; }

        public ContentEventArgs(string content)
        {
            Content = content;
        }
    }

    public class Car
    {
        //public event EventHandler DataChanged
        //skal laves om til
        public event EventHandler<ContentEventArgs> DataChanged;

    }

    public class LetsTestIt
    {
        public void Test()
        {
            Car car = new Car();
            car.DataChanged += new EventHandler<ContentEventArgs>(car_DataChanged);
        }

        void car_DataChanged(object sender, ContentEventArgs e)
        {
            Console.WriteLine(e.Content);
        }
    }

Hvis du kigger den her kode, så er der lidt du skal ændre i din egen. Men det står beskrevet i overstående også.

Håber ud får til det til virke.
Avatar billede Jim Rasmussen Novice
07. juli 2011 - 07:25 #45
It works like a charm! (:

Men hvorfor ikke bare lave ContentEventArgs propertien således

public class ContentEventArgs : EventArgs
    {
        public string Content { get; set; }
    }

Hvad gør nedenstående godt for? (:
public ContentEventArgs(string content)
{
    Content = content;
}
Avatar billede Syska Mester
07. juli 2011 - 15:23 #46
Det er bare en constructor, så jeg er sikker på at huske at sende en string med.

Jeg synes ikke det er smart at skulle sætte properties som mere eller mindre er nødvendige for at en given klasse er værd at bruge.

Properties kan bruges til optional information, hvilket jeg i den her sammenhæng, ikke synes Content er.

mvh
Avatar billede janus_007 Nybegynder
07. juli 2011 - 20:10 #47
"Jeg synes ikke det er smart at skulle sætte properties som mere eller mindre er nødvendige for at en given klasse er værd at bruge."

Enig... man kan nærmest opfatte det som required values når det kommer til dataobjekter.
Avatar billede Syska Mester
07. juli 2011 - 20:51 #48
Præcis ...

Need to have ... og nice to have.

Derfor kan det til tider pisse mig af at ting kræver en default constructor ( Når man bruger den til ORM ) ... da nogen object bare ikke er en skid værd uden data. :-)

mvh
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