【问题标题】:What if I only want one class to access my form's controls?如果我只想让一个班级访问我的表单控件怎么办?
【发布时间】:2011-08-18 01:01:07
【问题描述】:

我在我的应用程序中实现了一个撤消/重做系统,但是因为它是一个独立于我的主窗体的类,它无法访问它的任何控件。目前,我将需要撤消或重做的每个控件都传递给类的构造函数,但它正在迅速成为我项目中最大的构造函数之一。

如果只允许这个类访问我的表单控件就好了。如果我将表单传递给构造函数,我仍然无法访问控件,因为它们都是私有的。我想简单的解决方案是将我需要使用的所有控件公开,但理想或优雅的解决方案是什么?

附:我已经阅读了有关为所需的所有内容提供公共属性并将表单传递给构造函数的技术,但这最终会成为相当多的属性,并且该解决方案在这种情况下似乎不太适用。

谢谢!

【问题讨论】:

  • 所以你不想有一个大的构造函数,但你想要一个大的类/系统,它会知道差异表单上的一些控件来处理重做/撤消。我认为问题出在其他地方,在您的设计中。如果您详细说明您想通过 Undeo/Redo 完成什么,我可以帮助您。

标签: c# winforms


【解决方案1】:

将 UI 控件或表单传递给类是非常、非常、非常少的好习惯。这只是一个正在酝酿中的维护/依赖噩梦。

您不希望您的班级盲目地了解您的表单控件,它应该关心的只是它的数据。

您的表单知道自己,知道需要保存的数据以及如何将其恢复到适当的控件。

如果您正在寻找的只是撤消/重做功能,那么您需要研究 Memento 设计模式。除非您有其他业务需求,否则您不需要创建一个完全属性的类。

用于纪念品图案。

一个简单的对象持有你想要保留的状态....

 internal class Memento: IMemento
    {
        private object _state;

        public void SetState(object state)
        {
            _state = state;
        }

        public object GetState()
        {
            return _state;
        }
    }

看守对象管理表单的纪念品。

 public class Caretaker
    {
        private Dictionary<int,IMemento> _mementos = new Dictionary<int,IMemento>();
        public void AddMemento(int tag, IMemento memento)
        {
            _mementos.Add(tag, memento);
        }

        public IMemento GetMemento(int tag)
        {

            if (_mementos.ContainsKey(tag))
            {
                return _mementos[tag];
            }

            return null;
        }
    }

表单在更改状态后将新的纪念品保存到看守者。我们利用对象类的极大灵活性...

private void SaveMemento()
{
            Memento memento = new Memento();
            string[] state = {TextBox1.Text, TextBox2.Text};//expand as needed
            memento.SetState(state);
            _caretaker.AddMemento(_currentStateIndex, memento);
            _currentStateIndex++;
}

表单会根据需要恢复。

private void RevertToPreviousState()
        {
            Memento memento = (Memento)_caretaker.GetMemento(--_currentStateIndex);
            string[] state = (string[]) memento.GetState();
            TextBox1.Text = state[0];
            TextBox2.Text = state[1];//expand as needed

        }

忘记了 IMemento -- 只是一个标记接口,以防您想将看守者放在另一个程序集中以实现完整的 Memento 模式。

public interface IMemento
    {
    }

【讨论】:

  • 感谢您的详尽回复,但我无法使用此系统。我的地图可能有数百万像素,因此将整个画布的状态保存为单个画笔笔触将是多余的。
  • 不打算详细介绍,但您可能只想将用户执行的每个操作保存为命令对象,其中包括一个 Undo 方法。查看命令模式。
  • 我基本上是这样做的,但我仍然需要参考 MapSizeChange 类/命令中的某些表单控件。
  • 我会重新考虑您的设计,因此您无需了解其他对象内的控件。我只是保存控件的名称和必要的数据。
【解决方案2】:

访问用于跟踪状态的控件并不是最好的方法,但是如果您想要这样做,那么我建议您通过反射访问私有的控件 http://social.msdn.microsoft.com/forums/en-US/clr/thread/ef7cc349-cf35-4b01-95b3-b71675f9b9d5/

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-08-02
    • 1970-01-01
    • 1970-01-01
    • 2011-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-23
    相关资源
    最近更新 更多