从外部对象管理wpf窗口

时间:2013-08-20 22:02:31

标签: c# wpf asp.net-mvc

我有一个应用程序,其中一个部分包含一组循环中的wpf窗口,发送一个业务对象以在模型中进行更改。像这样的东西(不是真正的代码):

class Window1 {

    BusinessObject obj;

    public Window1 (BusinessObject obj){
        this.obj = obj;
    }

    /*  Things showing obj info and modifying it. */

    public void on_Button_Next_Click(object sender, EventArgs args){
        new Window2(obj).Show();
       this.close();
    }
}

 class Window2 {

    BusinessObject obj;

    public Window2 (BusinessObject obj){
        this.obj = obj;
    }

    /*  Things showing obj info and modifying it. */

    public void on_Button_Next_Click(object sender, EventArgs args){
        new Window3(obj).Show();
       this.close();
    }
}

class Window3 {

    BusinessObject obj;

    public Window3 (BusinessObject obj){
        this.obj = obj;
    }

    /*  Things showing obj info and modifying it. */

    public void on_Button_Next_Click(object sender, EventArgs args){
        if (!obj.Finished) {
            new Window1(obj).Show();
            this.close();
        }
    }
}

通过新的更改,而不是始终是W1 - > W2 - > W3 - > W1,取决于业务对象的信息,每次迭代有4种不同的路径:W1 - > W2 - > W3 - > W2 - > W1或W1 - > W2 - > W3 - > W1 - > W2 - > W1,所以我需要为每个窗口都有一个状态。

class Window1 {
    BusinessObject obj;

    public Window1 (BusinessObject obj, int path, int repetition){
        this.obj = obj;
    }

    /*  Things showing obj info and modifying it. */

    public void on_Button_Next_Click(object sender, EventArgs args){
        if (path == 0) {
           new Window2(obj).Show();
           this.close();
        }
        if (path == 1 && repetition = 0){
            new Window2(obj, path, 0).Show();
            this.close();
        }
        else {
            new Window3(obj, path, 1).Show();
            this.close();
        }
    }
}

是否可以通过窗口管理器控制窗口而不是这样做?喜欢这个

while (true) {
    new Window1(obj).Show();
    wait(Window1);
    new Window2(obj).Show();
    wait(Window2); 
     if (obj.Condition1){
        new Window3(obj).Show();
    } else {
        new Window1(obj).Show();
         wait(Window1);
         new Window3(obj).Show();
    }
}

如果可能,这将是一个不好的做法?

1 个答案:

答案 0 :(得分:0)

虽然我不太清楚你想要实现的目标实际上有多大意义,但这里有一个可能的解决方案(假设你可以配置你需要的规则)。

首先,我们有一个可配置的“StateMachine”,您可以将业务对象的状态耦合到应该创建的下一个窗口。

public class StateMachine
{
    private readonly List<Tuple<Predicate<MyBusinessObject>, Func<MyBusinessObject, StateMachine, Window>>> _matchList;
    public StateMachine()
    {
        _matchList = new List<Tuple<Predicate<MyBusinessObject>, Func<MyBusinessObject, StateMachine, Window>>>();
    }

    public void RegisterState(Predicate<MyBusinessObject> predicate, Func<MyBusinessObject, StateMachine, Window> windowFactory)
    {
        _matchList.Add(Tuple.Create(predicate, windowFactory));
    }
    public Window Next(MyBusinessObject currentState)
    {
        var entry = _matchList.Where(m => m.Item1(currentState)).FirstOrDefault();
        if (entry != null)
            return entry.Item2(currentState, this);
        return null;
    }
}

在创建窗口之前,在应用程序初始化时,您可以创建状态机的实例并配置规则:

    public StateMachine InitializeStateMachine()
    {
        var stateMachine = new StateMachine();
        // If condition1 is true open Window2
        stateMachine.RegisterState(bo => bo.Condition1, (bo, sm) => new Window2(bo, sm));
        // If the sum is more than 12.5 and some value is not 42 open Window3
        stateMachine.RegisterState(bo => bo.SomeSum > 12.5 && bo.SomeValue != 42, (bo, sm) => new Window3(bo, sm));
        // The answer to life and everything will open Window4
        stateMachine.RegisterState(bo => bo.SomeValue == 42, (bo, sm) => new Window3(bo, sm));
        // More rules ...
        // If no other condition matches, open Window1
        stateMachine.RegisterState(bo => true, (bo, sm) => new Window1(bo, sm));
        return stateMachine;
    }

您的窗口类都需要实现一个构造函数,该构造函数接受业务对象实例和状态机实例。当需要打开一个新窗口时,他们只需要在状态机上调用Next

public class Window1 : Window
{
    private readonly StateMachine _stateMachine;
    private readonly MyBusinessObject _businessObject;

    public Window1(MyBusinessObject businessObject, StateMachine stateMachine)
    {
        _stateMachine = stateMachine;
        _businessObject = businessObject;
    }

    public void on_Button_Next_Click(object sender, EventArgs args)
    {
        // look ma, no logic ...
        var nextWindow = _stateMachine.Next(_businessObject);
        if (nextWindow != null)
            nextWindow.Show();
        this.Close();
    }
}

如果逻辑更复杂,或者不仅仅依赖于业务对象本身的状态,则需要进行一些调整以将这些考虑在内。