简体   繁体   中英

How to make event of instance work?

i'm trying to implement decorator pattern using Windows Forms and have some questions here. When I call event of previous decorated instance it partly doesn't work and i can't figure out why. Part that doesn't work includes actions with Windows.Forms.Form i implement, but Console.WriteLine work perfectly. You may test my code below, but you need 11.txt file on your desktop (or change path) to make it work;

using System.Windows.Forms;
using System.IO;
using System;

class Decorator
{
    class UpgradedStream : Form
    {
        public TrackBar trbRead;
        public Button btnRead;
        public TextBox txtBox;

        public UpgradedStream()
        {
            this.Width = 600;
            this.Height = 600;
            this.Text = "Decorating Stream class";

            trbRead = new TrackBar();
            trbRead.Width = 300;
            trbRead.Value = 2;

            btnRead = new Button();
            btnRead.Click += new EventHandler(ReadFile);
            btnRead.Text = "&Slide bar abowe!";
            btnRead.Top = 40;
            btnRead.Width = 150;

            txtBox = new TextBox(); ;
            txtBox.Multiline = true;
            txtBox.Top = 75;
            txtBox.Width = 550;
            txtBox.Height = 450;
            txtBox.ScrollBars = ScrollBars.Vertical;

            this.Controls.Add(btnRead);
            this.Controls.Add(trbRead);
            this.Controls.Add(txtBox);
        }

        public virtual void ReadFile(Object source, EventArgs e)
        {
            Text = "123"; //doesn't work in decorator chain
            Console.WriteLine("works"); //works
        }
    }

    class DecoratedStream : UpgradedStream
    {
        public UpgradedStream previous;
        public FileStream fin = null;
        public int i, count = 0;

        public DecoratedStream(UpgradedStream us)
        {
            previous = us;


            fin = new FileStream("11.txt", FileMode.Open);
        }

        public override void ReadFile(Object source, EventArgs e)
        {
            previous.ReadFile(source, e);
            try
            {
                fin = new FileStream("C:\\Users\\Vitaliy\\Desktop\\11.txt", FileMode.Open);

                do
                {
                    count++;
                    i = fin.ReadByte();
                    if (i != -1) txtBox.Text += (char)i;
                } while (i != -1 && count < fin.Length * (trbRead.Value * 0.1));
            }
            catch (IOException exc)
            {
                txtBox.Text += ("Error Input-Output:\n" + exc.Message);
            }
            finally
            {
                txtBox.Text += "\r\n";
                txtBox.Text += String.Format("WRITED: {0} SYMBOLS\r\n", Convert.ToInt32(fin.Length * (trbRead.Value * 0.1)));
                txtBox.Text += "\r\n";

                if (fin != null) fin.Close();
                count = 0;
            }
        }
    }

    class PasswordForm : Form
    {
        private Label lblPassForm;
        private Button btnPassForm;
        private TextBox tbxPassForm;

        public PasswordForm()
        {
            this.Text = "Enter password";
            lblPassForm = new Label();
            lblPassForm.Text = "password - 123";

            tbxPassForm = new TextBox();
            tbxPassForm.Top = 30;

            btnPassForm = new Button();
            btnPassForm.Text = "&OK";
            btnPassForm.Top = 50;
            btnPassForm.Click += new EventHandler(ClosePassForm);
            btnPassForm.DialogResult = DialogResult.OK;

            this.Controls.Add(lblPassForm);
            this.Controls.Add(tbxPassForm);
            this.Controls.Add(btnPassForm);
        }
        public void ClosePassForm(Object source, EventArgs e)
        {
            password = tbxPassForm.Text;
            this.Close();
        }

        public String password { get; set; }
    }

    class AskPassword : UpgradedStream
    {
        public PasswordForm PassForm;

        private string password;

        protected internal UpgradedStream previous;

        public AskPassword(UpgradedStream us)
        {
            previous = us;
        }

        public override void ReadFile(Object source, EventArgs e)
        {
            previous.ReadFile(source, e);

            using (PassForm = new PasswordForm())
            {
                if (PassForm.ShowDialog() == DialogResult.OK)
                {
                    if (PassForm.password == "123")
                        previous.ReadFile(source, e);
                }
            }
        }
    }


    static void Main()
    {
        Application.EnableVisualStyles();

        UpgradedStream up = new UpgradedStream();
        DecoratedStream dk = new DecoratedStream(up);
        AskPassword ask = new AskPassword(dk);

        Application.Run(ask);
    }
}

for exapmple

public virtual void ReadFile(Object source, EventArgs e)
{
    Text = "123"; //doesn't work in decorator chain
    Console.WriteLine("works"); //works
}

This is because txtBox is an instance field and is not shared amongst the classes in your decorator 'chain'. If you alter the declaration so that's it's static like:

public static TextBox txtBox;

then you'll observe behaviour that might be closer to what you're expecting. I'm not suggesting this is the preferred solution, just that it illustrates the problem.

You might be better served by separating presentation and behaviour. This will create an, arguably, cleaner solution.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM