帮助设计管理器类

本文关键字:管理器 帮助 | 更新日期: 2023-09-27 18:09:39

我正在设计一个UI管理器类,将管理我所有的UI元素(这是一个XNA游戏,所以没有现有的UI框架),但我想知道如何处理的情况下,我希望UI管理器有特殊的访问数据的UI元素,其他类不能访问。

例如,我想有一个SetFocus方法来聚焦一个特定的元素,这个方法需要确保先前聚焦的元素失去焦点。单个UI元素本身不能处理这个,因为它们不能访问UI元素列表,这意味着管理器必须处理它,但是我如何允许管理器和只有管理器在UI元素上设置变量?

我想到只是将当前聚焦的元素存储在管理器上,但是我不是特别喜欢这个解决方案,并且给定单个UI元素,我想查询它以找出它是否有焦点。即使将当前关注的元素存储在管理器中是有意义的,因为它只是一个单独的变量,但如果数据存储在管理器中,我还需要处理其他事情,这些事情需要数组将数据与元素关联起来,这似乎违背了OOP的目的。

我知道我不需要拥有它,以便经理是唯一访问这些数据的人,我可以让所有的数据公开,但这不是一个好的设计…

帮助设计管理器类

您正在寻找的是c++友元概念的c#等效。正如你在链接的帖子中读到的,"最接近的可用(它不是很接近)是InternalsVisibleTo"(引用乔恩·斯基特的话)。但是使用InternalsVisibleTo来完成你想要的东西意味着你必须将整个应用程序分解成每个类的库,这可能会创建一个DLL地狱。

以MattDavey的例子为基础得到了我:

interface IFocusChecker
{
    bool HasFocus(Control control);
}
class Manager : IFocusChecker
{
    private Control _focusedControl;
    public void SetFocus(Control control)
    {            
        _focusedControl = control;
    }
    public bool HasFocus(Control control)
    {
        return _focusedControl == control;
    }
}
class Control
{
    private IFocusChecker _checker;
    public Control(IFocusChecker checker)
    {
        _checker = checker;
    }
    public bool HasFocus()
    {
        return _checker.HasFocus(this);
    }
}

Control是否有焦点现在只存储在Manager中,只有Manager可以改变焦点的Control

一个简单的例子,如何把东西放在一起,为了完整:

class Program
{
    static void Main(string[] args)
    {
        Manager manager = new Manager();
        Control firstControl = new Control(manager);
        Control secondControl = new Control(manager);
        // No focus set yet.
        Console.WriteLine(string.Format("firstControl has focus? {0}",
            firstControl.HasFocus()));
        Console.WriteLine(string.Format("secondControl has focus? {0}",
            secondControl.HasFocus()));
        // Focus set to firstControl.
        manager.SetFocus(firstControl);
        Console.WriteLine(string.Format("firstControl has focus? {0}",
            firstControl.HasFocus()));
        Console.WriteLine(string.Format("secondControl has focus? {0}",
            secondControl.HasFocus()));
        // Focus set to firstControl.
        manager.SetFocus(secondControl);
        Console.WriteLine(string.Format("firstControl has focus? {0}",
            firstControl.HasFocus()));
        Console.WriteLine(string.Format("secondControl has focus? {0}",
            secondControl.HasFocus()));
    }
}

在控件本身上设置一个隐式相对于其他控件状态的变量可能是一个糟糕的设计决策。"焦点"的概念是在一个更高的层次上关注的,或者是一个窗口,或者更好的是,一个用户(用户是进行聚焦的人)。因此,应该在窗口或用户级别存储对焦点控件的引用,但除此之外,应该有一种方法可以在控件从用户获得/失去焦点时通知它们——这可以通过用户/管理器上的事件或任何标准通知模式来完成。

class Control
{
    public Boolean HasFocus { get; private set; }
    internal void NotifyGainedFocus()
    {
        this.HasFocus = true;
        this.DrawWithNiceBlueShininess = true;
    }
    internal void NotifyLostFocus()
    {
        this.HasFocus = false;
        this.DrawWithNiceBlueShininess = false;
    }
}
class User // or UIManager
{
    public Control FocusedControl { get; private set; }
    public void SetFocusOn(Control control)
    {
        if (control != this.FocusedControl)
        {
            if (this.FocusedControl != null)
                this.FocusedControl.NotifyLostFocus();
            this.FocusedControl = control;
            this.FocusedControl.NotifyGainedFocus();
        }
    }
}

免责声明:我从来没有写过一个UI库,我可能在说完全无稽之谈。