从另一个 class 更新一个 pictureBox.Image

Updating a pictureBox.Image from another class

更新: 我很确定我找到了原因,我会在确定后立即用我的发现更新这个问题。这与将 2 个用户控件放在彼此上方有关,我在后面的一个上画图,这就是为什么我看不到更改的原因!我必须检查计时器的哈希码才能确定涉及 2 个计时器。


我正在开发一个 winforms 应用程序,我应用了 MVP 模式来分离职责和内容...(应用了被动视图方法,并且还触发事件以要求相应的演示者执行操作) .

我在这里也检查了其他问题和许多其他相关主题,但没有任何帮助...

问题描述:我在SplitContainerpanel中添加了一个UserControlSubView)在 Form (MainView) 中。此 SubView 有自己的演示者 (SubPresenter),要求它在用户从 [=22= 触发时切换其背景 (SwitchBackground()picturebox) ].

问题: SwitchBackground() 方法在 MainView(实际上是 MainPresenter),但 SubView 上的更改未显示 。我还检查了(或至少尝试正确地做到这一点 :))该方法是否需要通过检查 InvokeRequired.

将上下文切换到 GUI 线程或其他内容

我很乐意就此问题提出任何建议,因为我被困在那里,无法进一步编程...

这是我为说明问题而编写的示例应用程序(对于完整的示例项目,我将其上传到 github:link):

子视图:

public interface ISubView
{
    void StartSwitchingBackground();
    void StopSwitchingBackground();
}

public partial class SubView : UserControl, ISubView
{
    private Bitmap plot;
    private Brush brush1;
    private Brush brush2;
    private int drawCount;

    private Timer timer;

    public SubView()
    {
        InitializeComponent();

        brush1 = new SolidBrush(Color.Yellow);
        brush2 = new SolidBrush(Color.Blue);

        timer = new Timer();
        timer.Tick += OnTick;
    }

    private void OnTick(object sender, EventArgs e)
    {
        SwitchBackground();
    }

    private void SwitchBackground()
    {

        if (InvokeRequired)
            Console.WriteLine("InvokeRequired");    // never happens, so i assume it is not considered a call from another thread...

        if (plot == null || plot.Size != pictureBox.Size)
            plot = new Bitmap((int)(pictureBox.Width*0.8), (int)(pictureBox.Height*0.8));

        using (Graphics g = Graphics.FromImage(plot))
        {
            int x = plot.Width / 2;
            int y = plot.Height / 2;
            int w = plot.Width / 4;
            int h = plot.Height / 4;

            if (drawCount % 2 == 0)
            {
                g.Clear(Color.White);
                g.FillRectangle(brush1, (x - w) / 2, (y - h) / 2, w, h);
            }
            else
            {
                g.Clear(Color.Black);
                g.FillRectangle(brush2, (x - w) / 2, (y - h) / 2, w, h);
            }
            drawCount++;
        }
        pictureBox.Image = plot;
    }

    public void StartSwitchingBackground()
    {
        if (!timer.Enabled)
            timer.Start();
        Console.WriteLine("started");
    }

    public void StopSwitchingBackground()
    {
        if (timer.Enabled) timer.Stop();
        Console.WriteLine("stopped");
    }

    private void btnStartSwitching_Click(object sender, EventArgs e)
    {
        StartSwitchingBackground();
    }

    private void btnStopSwitching_Click(object sender, EventArgs e)
    {
        StopSwitchingBackground();
    }
}

副主持人:

public class SubPresenter
{
    private ISubView view;

    public SubPresenter(ISubView view)
    {
        this.view = view;
    }

    public void SwitchBackground()
    {
        view.StartSwitchingBackground();
    }

    public void StopSwitching()
    {
        view.StopSwitchingBackground();
    }
}

主视图:

public interface IMainView
{
    ISubView SubView { get; }
    event EventHandler SwitchEventTriggered;
    event EventHandler StopSwitchEventTriggered;
}

public partial class MainView : Form, IMainView
{
    private SubView subView;
    public MainView()
    {
        InitializeComponent();

        subView = new SubView();
        splitContainer1.Panel2.Controls.Add(subView);
        subView.Dock = DockStyle.Fill;
        subView.Anchor = AnchorStyles.Top & AnchorStyles.Left;
        splitContainer1.Resize += splitContainer1_Resize;
    }

    void splitContainer1_Resize(object sender, EventArgs e)
    {
        subView.Size = splitContainer1.Panel2.Size;
    }

    private void btnStart_Click(object sender, EventArgs e)
    {
        StartSwitching();
    }

    private void StartSwitching()
    {
        OnStartSwitchingTriggered();
    }

    private void OnStartSwitchingTriggered()
    {
        var handler = SwitchEventTriggered;
        if (handler == null) return;
        handler(this, EventArgs.Empty);
    }

    private void btnStop_Click(object sender, EventArgs e)
    {
        StopSwitching();
    }

    private void StopSwitching()
    {
        OnStopSwitching();
    }

    private void OnStopSwitching()
    {
        var handler = StopSwitchEventTriggered;
        if (handler == null) return;
        handler(this, EventArgs.Empty);
    }

    public ISubView SubView { get { return this.subView; } }
    public event EventHandler SwitchEventTriggered;
    public event EventHandler StopSwitchEventTriggered;
}

主讲人:

public class MainPresenter { private readonly IMainView mainView;

    private readonly SubPresenter subPresenter;

    public MainPresenter(IMainView view)
    {
        this.mainView = view;
        this.subPresenter = new SubPresenter(mainView.SubView);
        mainView.SwitchEventTriggered += OnSwitchEventTriggerd;
        mainView.StopSwitchEventTriggered += OnStopSwitchEventTriggered;
    }

    private void OnStopSwitchEventTriggered(object sender, EventArgs e)
    {
        subPresenter.StopSwitching();
    }

    private void OnSwitchEventTriggerd(object sender, EventArgs e)
    {
        subPresenter.SwitchBackground();
    }
}

入口点:

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        MainView mainView = new MainView();
        MainPresenter mainPresenter = new MainPresenter(mainView);

        Application.Run(mainView);
    }
}

您在 MainView 中有两个 SubView 实例。 只使用subView1,可以删除所有出现的subView;

最低限度的修复是替换:

public ISubView SubView { get { return this.subView; } }

与:

public ISubView SubView { get { return this.subView1; } }