1

UCCreateProfile.ascx (プロファイル データの作成/編集に使用) と UCProfileList.ascx (GridView でのプロファイル データの表示に使用) という名前の 2 つのユーザー コントロールがあります。新しいプロファイルが作成されるたびに、UCProfileList コントロールを更新して新しいエントリを表示したいと考えています。

上記の問題に対する最善の解決策は、オブザーバーパターンに行くことです。私の場合、UCCreatedProfile は Subject/Observable であり、UCProfileList は Observer であり、オブザーバーが初期化されるとパターン定義に従って、誰が私の Subject/Observable であるかを認識し、Subject/Observable リストに追加します。そのため、Subject/Observable で変更が発生するたびに通知されます。

このパターンは私の要件に最も適していますが、次のようにこれを実装するのに問題はほとんどありません。

私は CMS (Umbraco) で作業していますが、物理コンテナー ページ (.aspx) はありません。私がしなければならないことは、次のコードを使用して UCProfileList (オブザーバー) onLoad イベントで UCCreateProfile (サブジェクト/オブザーバブル) を見つけることです。

private Control FindCreateProfileControl()
{
     Control control = null;
     Control frm = GetFormInstance();
     control = GetControlRecursive(frm.Controls);

      return control;
}

GetFormInstance() メソッドの場所

private Control GetFormInstance()
    {
        Control ctrl = this.Parent;
        while (true)
        {
            ctrl = ctrl.Parent;
            if (ctrl is HtmlForm)
            {
                break;
            }
        }
        return ctrl;
    }

GetControlRecursive() メソッドは

 private Control GetControlRecursive(ControlCollection ctrls)
    {
        Control result = null;
        foreach (Control item in ctrls)
        {
            if (result != null) break;
            if (item is UCCreateProfile)
            {
                result = item;
                return result;
            }
            if (item.Controls != null)
                result = GetControlRecursive(item.Controls);
        }
        return result;
    }

このようにして、UCProfileList (Observer) で UCCreateProfile (Subject/Observable) ユーザー コントロールを見つけることができますが、(Subject/Observable) を見つける方法はそれほど速くありません。ご覧のとおり、すべてのコントロールをループして最初に HtmlForm コントロールを見つけ、次に HtmlForm コントロールの下にあるすべての子コントロールをループして、探している適切なコントロールを見つける必要があります。

次に、コンテナ内のユーザー コントロールの配置が非常に重要な場合、私のコードは UCCreatedProfile.ascx (Subject/Observable) が UCProfileList.ascx (Observer) の前に配置されている場合にのみ機能します。しかし、誰かがこれら 2 つのコントロールの位置を変更すると、私のコードは機能しなくなります。

したがって、これらの問題を取り除くには、コントロールの位置に関係なく、より高速に機能するソリューションが必要です。

以下に説明するように、いくつかの解決策を見つけました。これを行う良い方法があれば教えてください。代替手段がある場合は、お知らせください。

私はセッションレベルの変数(を含む辞書Dictionary<ISubject, List<Observer>>)を持っています。最初に初期化/ロードされたユーザー コントロールに関係なく、ユーザー コントロールはこのディクショナリに自身を追加します。
Subject/Observable が最初に追加された場合、対応するオブザーバーがこのディクショナリで見つかります。
Observer が最初に追加された場合、null エントリでディクショナリに追加されます。サブジェクトが追加されると、関連付けが行われます。

よろしく、

/リズワン

4

1 に答える 1

2

Observer パターンは、イベントとデリゲートを介して .NET に実装するのが最適です。イベントとデリゲートを使用すると、Dictionary言及は完全に不要になります。たとえば、以下のコードを参照してください (重要な部分のみを示します)。

public partial class UserProfile : System.Web.UI.UserControl
{
    //This is the event handler for when a user is updated on the UserProfile Control
    public event EventHandler<UserUpdatedEventArgs> UserUpdated;

    protected void btnUpdate_Click(object sender, EventArgs e)
    {
        //Do whatever you need above and then see who's subscribed to this event
        var userUpdated = UserUpdated;
        if (userUpdated != null)
        {
            //Initialize UserUpdatedEventArgs as you want. You can, for example,
            //pass a "User" object if you have one
            userUpdated(this,new UserUpdatedEventArgs({....}));
        }
    }
}

public class UserUpdatedEventArgs : EventArgs
{
    public User UserUpdated {get;set;}
    public UserUpdatedEventArgs (User u)
    {
        UserUpdated=u;
    }
}

上のコントロールUserUpdatedからイベントをサブスクライブするのは、次のように簡単です。UserProfileUserListControl

public partial class UserList : System.Web.UI.UserControl
{
    protected void Page_Load(object sender, EventArgs e)
    {
        //Find the UserProfile control in the page. It seems that you already have a 
        //recursive function that finds it. I wouldn't do that but that's for another topic...
        UserProfile up = this.Parent.FindControl("UserProfile1") as UserProfile;
        if(up!=null)
           //Register for the event
           up.UserUpdated += new EventHandler<UserUpdatedEventArgs>(up_UserUpdated);
    }

    //This will be called automatically every time a user is updated on the UserProfile control
    protected void up_UserUpdated(object sender, UserUpdatedEventArgs e)
    {
        User u = e.UserUpdated;
        //Do something with u...
    }
}
于 2012-09-04T14:21:31.567 に答える