yellow_nimbus
yellow_nimbus

Reputation: 343

Way of drawing on picturebox in different class

I'm currently working on a program in WinForms that will require a lot of special logic for rendering and mouse clicks on a PictureBox. I'd rather not have all of that logic stored in a custom control or even worse the main form that hosts the picture box. An added complication is there are certain objects that need to be known about in order to draw them correctly or handle clicking them.

Currently, the only idea I have is to make separate "Renderer" and "MouseHandler" classes that have a handle to the picture box and I can handle whatever events inside there. The issue is doing this while maintaining an MVP structure.

So, here's a little example code to better explain what's going on.

Main Form

public partial class Form1 : Form, IView
{
    private Renderer _render;
    private MouseHandler _mouseHandler;

    public Form1() { InitializeComponent(); }

    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);

        _render = new Renderer(Picbox);
        _mouseHandler = new MouseHandler(Picbox);
    }

    #region Implementation of IView

    public string FirstName { get; set; }
    public string LastName { get; set; }

    #endregion
}

Presenter for Main Form

public class Presenter
{
    private readonly IView _view;
    private readonly Model _model;

    public Presenter(IView view)
    {
        _view = view;
        _model = new Model("John", "Doe");
    }
}

Renderer

public class Renderer
    {
        private readonly PictureBox _pictureBox;

        public Renderer(PictureBox pictureBox)
        {
            _pictureBox = pictureBox;
            _pictureBox.Paint += PictureBoxOnPaint;
        }

        private static void PictureBoxOnPaint(object sender, PaintEventArgs e)
        {
            // TODO: Draw stuff like First and Last Name
        }

        public void Refresh() { _pictureBox.Invalidate(); }
    }

Model

public class Model
{
    private string FirstName { get; set; }
    private string LastName { get; set; }

    public Model(string firstName, string lastName)
    {
        FirstName = firstName;
        LastName = lastName;
    }
}

I cannot figure out a way to have the Renderer draw FirstName and LastName from the Main View's model without:

A. Giving the parent hosting the PictureBox the job of pushing information to the auxiliary classes by pushing the model info to the view from the presenter, then having the view push that to the Renderer.

or B. Adding a reference to the Forms library in the presenter to tie everything together. This would allow me to make views out of the auxillary classes and add a PictureBox property, but I'd like to avoid this in case the view turns into an MVC Application or WPF Application and the view does not use windows forms.

Is there any way I can get these auxiliary classes to work? Or is there a better method for this entirely? I'd hate to think I'm doomed to cram all of it in a custom control. Thanks in advance for any suggestions!

Upvotes: 0

Views: 505

Answers (1)

quetzalcoatl
quetzalcoatl

Reputation: 33506

In place where you instantiate the renderer, why don't you give it a reference to the model object that contains the data? Surely, it is the "A" way, but as you are 'manually' binding it hard to the PictureBox, so I do not see anything wrong in additionally passing it the model instance altogether with the picbox. It seems natural to me that when I'm creating an object and configuring it - I configure it fully. Otherwise, you'd have to add some renderer-building-layer, because, naturally, the renderer simply must get the data somehow..

Actually, giving the model to the renderer is not (at least for me) any breach in the architecture and does not place any extra burden/logic on the 'hoster', provided that you will pass 'the whole model' and the renderer will be responsible for reading the actual data it needs. IMHO, in such way, everything would be exactly right in its place.

Upvotes: 1

Related Questions