none
子クラスから親クラスへの変更通知 RRS feed

  • 質問

  • お世話になります。
    以下のようなクラスを定義しておりますが、UserCollection配列の1データの
    SelectプロパティがTrueになったデータをUserInfoクラス側のUserId、UserNmへ
    反映させたいのですが、このようなことは可能でしょうか?
    よろしくお願いします。

        public class UserInfo : INotifyPropertyChanged
        {

            private string userid;
            private string usernm;
            private ObservableCollection<UserInfo> usercollection;

            public string UserId
            {
                get { return userid; }
                set
                {
                    if (userid == value)
                    {
                        return;
                    }
                    userid = value;
                    OnPropertyChanged("UserId");
                }
            }

            public string UserNm
            {
                get { return usernm; }
                set
                {
                    if (usernm == value)
                    {
                        return;
                    }
                    usernm = value;
                    OnPropertyChanged("UserNm");
                }
            }

            public ObservableCollection<ClientOrderInfo> UserCollection
            {
                get { return usercollection; }
                set
                {
                    if (usercollection == value)
                    {
                        return;
                    }
                    usercollection = value;
                    OnPropertyChanged("UserCollection");
                }
            }
        }

        public class UserCollection : INotifyPropertyChanged
        {

            private bool select;
            private string userid;
            private string usernm;

            public bool Select
            {
                get { return select; }
                set
                {
                    if (select == value)
                    {
                        return;
                    }
                    select = value;
                    OnPropertyChanged("Select");
                }
            }

            public string UserId
            {
                get { return userid; }
                set
                {
                    if (userid == value)
                    {
                        return;
                    }
                    userid = value;
                    OnPropertyChanged("UserId");
                }
            }

            public string UserNm
            {
                get { return usernm; }
                set
                {
                    if (usernm == value)
                    {
                        return;
                    }
                    usernm = value;
                    OnPropertyChanged("UserNm");
                }
            }

        }

    }

    2013年1月19日 7:22

回答

  • お世話になっております。

    大変参考になりました。
    ありがとうございました。

    ※既存コードの中のやりたいことに該当する部分だけを簡略化してコードを
    掲載してしまったため、INotifyPropertyChangedインタフェースに関する
    メソッド実装など削除してしまいました。
    補完の手間までかけさせてしまい、大変申し訳ありません。

    • 回答としてマーク schsch_21 2013年1月19日 9:36
    2013年1月19日 9:36

すべての返信

  • 方法論はいくつかありますが・・・
    一番単純なのは、子クラスにイベントを定義して、親クラス側で全ての子クラスのイベントハンドラを登録してウォッチするという方法です。
    ただ、この方法はイベントハンドラの登録/解除処理が複雑になる上、何らかの要因でイベントハンドラの解除をミスるとメモリリークに繋がるのでお勧めはできません。

    個人的にお勧めなのは、イベントリスナを作成してこれを経由してイベントを通知するという方法です。

        public class UserInfoListener
        {
            private static UserInfoListener _instance = new UserInfoListener();
    
            private UserInfoListener() { }
    
            public static UserInfoListener Instance
            {
                get { return _instance; }
            }
    
            public event EventHandler SelectChanged;
    
            public void OnSelectChanged(UserInfoChild child)
            {
                SelectChanged(child, EventArgs.Empty);
            }
        }
    
        public class UserInfo : INotifyPropertyChanged
        {
            private ObservableCollection<UserInfoChild> children = new ObservableCollection<UserInfoChild>();
     
            public ObservableCollection<UserInfoChild> Children
            {
                get { return children; }
                set
                {
                    if (children == value)
                    {
                        return;
                    }
                    children = value;
                    OnPropertyChanged("Children");
                }
            }
    
            public UserInfo()
            {
                UserInfoListener.Instance.SelectChanged += UserInfoListener_SelectChanged;
            }
    
            ~UserInfo()
            {
                UserInfoListener.Instance.SelectChanged -= UserInfoListener_SelectChanged;
            }
    
            private void UserInfoListener_SelectChanged(object sender, System.EventArgs e)
            {
                if (!this.Children.Contains((UserInfoChild)sender)) return;
    
                //ここに処理を書く
                MessageBox.Show(((UserInfoChild)sender).UserNm);
            }
    
            public void OnPropertyChanged(string propertyName)
            {
                if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
    
            public event PropertyChangedEventHandler PropertyChanged;
        }
     
        public class UserInfoChild : INotifyPropertyChanged
        {
            private bool select;
            private string usernm;
     
            public bool Select
            {
                get { return select; }
                set
                {
                    if (select == value)
                    {
                        return;
                    }
                    select = value;
                    OnPropertyChanged("Select");
                    UserInfoListener.Instance.OnSelectChanged(this);
                }
            }
     
            public string UserNm
            {
                get { return usernm; }
                set
                {
                    if (usernm == value)
                    {
                        return;
                    }
                    usernm = value;
                    OnPropertyChanged("UserNm");
                }
            }
    
            public void OnPropertyChanged(string propertyName)
            {
                if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
    
            public event PropertyChangedEventHandler PropertyChanged;
        }

    ※注:元に提示されていたコードはビルドが通らない&クラス構成がもうひとつよくわからかったので、説明する上で最低限必要なコードに変更しています。

    UserInfoListenerクラスに通知用イベントとトリガメソッドを用意し、親クラスのインスタンス時にこの通知用イベントにハンドラを登録します。
    子クラスの側でトリガメソッドを呼び出してやれば、UserInfoListenerを経由して親クラスにイベントが通知されます。
    また、UserInfoListenerは利便性のためにSingletonで実装しています。

    この方法だと、イベントハンドラの管理は親クラスだけで済み、子クラス側はトリガを呼ぶだけで良いので扱いが楽になります。

    以上、参考まで。


    • 編集済み みっと 2013年1月19日 9:00
    • 回答としてマーク schsch_21 2013年1月19日 9:36
    • 回答としてマークされていない schsch_21 2013年1月19日 9:36
    2013年1月19日 8:59
  • お世話になっております。

    大変参考になりました。
    ありがとうございました。

    ※既存コードの中のやりたいことに該当する部分だけを簡略化してコードを
    掲載してしまったため、INotifyPropertyChangedインタフェースに関する
    メソッド実装など削除してしまいました。
    補完の手間までかけさせてしまい、大変申し訳ありません。

    • 回答としてマーク schsch_21 2013年1月19日 9:36
    2013年1月19日 9:36