0

2 つのプロパティを持つカスタム クラスの一般的なリストがあります。これらのプロパティは、フォームと別のフォームの間の関係を保存します。リストは、階層リスト (親子) 関係として構造化されています。私ができるようにしたいのは、関数に渡される親フォーム参照に基づいてすべてのフォームのリストを取得することです。これを行う最善の方法は、再帰的アプローチを使用した LINQ クエリを使用することだと考えています。誰かが私を正しい方向に向けることができると確信しています

これはリストで使用されるクラスです

class FormStack    {

    #region Declares

    private Form _form;
    private Form _parent;

    #endregion

    #region Constructor

    static FormStack()
    {
    }

    #endregion

    public Form Form
    {
        get { return _form; }
        set { _form = value; }
    }

    public Form Parent
    {
        get { return _parent; }
        set { _parent = value; }
    }

}

したがって、メソッドを呼び出してフォーム参照を関数に渡し、この親に関連するすべての子フォームを取得できるようにしたいと考えています。

これは私がつまずいたコードの一部です

// create a lookup list
var list = formStack.ToLookup( p => object.ReferenceEquals( p.Parent, parent ) );

// create a function
Func<IEnumerable<Form>, IEnumerable<Form>> recurse = null;
recurse = qs =>
{
    return
        qs
            .Concat(
                from q in qs
                from q2 in recurse( list[] )
                select q2 );
};

// filter the list
var children = recurse( list[parent] ).ToList();

標準の CRUD 機能を備えた winform アプリケーションがあります。顧客のリストがあり、各顧客が複数の住所を持つことができ、これらの住所のそれぞれに複数の建物があるとしましょう。フォームを構造化した方法では、顧客のリストがあり、このリストから詳細フォームを開くことができます特定の顧客。このフォームには、顧客の詳細とリスト内のすべてのアドレスが含まれています。このリストにより、ユーザーはリスト内の住所を選択し、建物などのリストを含む住所詳細フォームを開くことができます。私の問題は、この顧客の詳細と関連するすべてのフォームを閉じたいことです。 . 私の考えは、フォーム間の関係を維持することでしたが、もっと良い方法があるのではないでしょうか???

4

2 に答える 2

0

わかりました、2 つの問題があるように思えます。1 つは構文エラー (recurse(list[])間違っている) ですが、もう 1 つは FormStack が実際にはスタックではないということです。これは 2 つの形式にすぎず、再帰チェーンを作成する方法はありません。私はあなたがこれを望んでいると思います:

public class FormStack : IEnumerable<Form> // or just implement SelectMany
{    
    public Form Form { get; set; }
    public FormStack Parent { get; set; }  
    //implement IEnumerable<Form> or the SelectMany method
}

次に、これを行うことができると思いますが、これは厄介なことのようです。

Func<FormStack, IEnumerable<Form>> recurse = qs =>
{
    return from q in qs
           select (new[] { qs.Form }).Concat(recurse(qs.Parent));
};

var list = recurse(formStack).ToList();

それは、クエリ構文を主張している場合です。

ただし、私があなただったら、それをすべて忘れて、あなたのためにすべてを行うために を実装IEnumerator<Form>します。

public class FormStack : IEnumerable<Form> 
{    
    public Form Form { get; set; }
    public FormStack Parent { get; set; }  
    public IEnumerator IEnumerable:GetEnumerator() 
    { 
        return (IEnumerator)GetEnumerator();
    }
    public IEnumerator<Form> GetEnumerator() 
    { 
        return new FormStackEnumerator(this);
    }
}
public class FormStackEnumerator : IEnumerator<Form>
{
    private FormStack _stack;
    private FormStack _first;
    public Form Current { get { return _stack.Form; } }
    object IEnumerator.Current { get { return Current; } }

    public FormStackEnumerator(FormStack stack)
    {
        _stack = stack;
        _first = stack;
    }
    public bool MoveNext()
    {
        if (_stack.Parent == null)
        {
            return false;
        }
        _stack = _stack.Parent;
        return true;
    }
    public void Reset() { _stack = _first; }
    void IDisposable.Dispose() { }
}

次に、メイン コードで行う必要があるのは次のとおりです。

var list = new List<Form>();
foreach (var node in formStack)
{
    list.Add(node.Form);
}

ところで、私は Form クラスを調べただけで (私は WinForms 開発者ではありません)、Forms 自体に Parent メンバーがあります。そのため、ノード型の構造でそれらをラップする必要はありません。それらはすでにノードです!これにより、すべてが簡単になります。

var list = new List<Form>();

Action<Control> recurse = target =>
{
    var form = target as Form;
    if (form != null)
    {
        list.Add(form);
        recurse(target.Parent);
    }
}
于 2012-11-05T07:17:25.743 に答える
0

ここに私が作ったものがあります:

すべてのフォームのベース フォームを作成します。

public class MyFormBase : Form
{
    public MyFormBase()
    {
        FormRepository.RegisterForm(this);
    }

    public MyFormBase(MyFormBase parent)
        : this()
    {
        Parent = parent;
    }

    public MyFormBase Parent { get; set; }
}

各フォームは、コンストラクターで渡される親を 1 つだけ持つことができます。

フォームを保存するためのリポジトリ(または類似のもの)を作成します->フォーム自体にすべての子を保存したくありません

//infrastructure - simulated with a static class
public static class FormRepository
{
    private static List<MyFormBase> _allForms = new List<MyFormBase>();

    public static void RegisterForm(MyFormBase form)
    {
        _allForms.Add(form);
    }

    public static void CloseFormAndChildren(MyFormBase form)
    {
        _allForms.Where(x => x.Parent.Equals(form)).ToList().ForEach(x => CloseFormAndChildren(x));
        form.Close();
    }
}

閉じたい任意のフォーム (子を含む) で CloseFormAndChildren を呼び出します。これはクロージングイベントで呼び出される可能性があります...

于 2012-11-06T15:58:04.993 に答える