2010-10-26 68 views
0

我有一个实现INotifyPropertyChanged接口的类。 如果我创建该对象的一个​​新实例,PropertyChanged事件在我从中检索到一个值后设置。C#自定义类使用INotifyPropertyChanged不通知作业

实施例:

MyItem itm = new MyItem(); //MyItem.PropertyChanged == null 
string test = itm.Value; //MyItem.PropertyChanged != null 

如果我分配ITM另一个MyItem的值,PropertyChanged事件保持为空。

例子:

itm = (MyItem)cboMyItemsCombobox.SelectedItem; // Properties for itm change to the values 
               // of the selected item, but PropertyChanged 
               // == null 

我认为问题出在部分我的自定义类的构造函数,但我不能完全肯定。

目标是有一个变量来保存记录的数据,称为mnuitm,绑定到文本框对象。当文本框中的文本发生更改时,将对mnuitm中的属性进行更改。当mnuitm中的属性发生更改时,将在文本框中进行更改。 如果我创建一个新的MenuItem并单独分配值,但如果将已填充的MenuItem分配给mnuitm不起作用,则此方法有效。

这是我的实际代码(希望),在这个问题上更清晰。

public partial class frmMenuItems : Form 
{ 
    private class MenuItem : INotifyPropertyChanged 
    { 
     private Int32 mid; 
     private string txt; 
     private string url; 
     private string scp; 

     public MenuItem() { } 

     public MenuItem(Int32 id, string txt, string url, string scp) 
     { 
      ID = id; 
      Text = txt; 
      URL = url; 
      Script = scp; 
     } 

     public Int32 ID 
     { 
      get 
      { 
       return mid; 
      } 
      set 
      { 
       if (mid != value) 
       { 
        mid = value; 
        NotifyPropertyChanged("ID"); 
       } 
      } 
     } 

     public string Text { 
      get 
      { 
       return txt; 
      } 
      set 
      { 
       if (txt != value) 
       { 
        txt = value; 
        NotifyPropertyChanged("Text"); 
       } 
      } 
     } 

     public string URL { 
      get 
      { 
       return url; 
      } 
      set 
      { 
       if (url != value) 
       { 
        url = value; 
        NotifyPropertyChanged("URL"); 
       } 
      } 
     } 

     public string Script { 
      get 
      { 
       return scp; 
      } 
      set 
      { 
       if (scp != value) 
       { 
        scp = value; 
        NotifyPropertyChanged("Script"); 
       } 
      } 
     } 

     public void Clear() 
     { 
      ID = 0; 
      Text = ""; 
      URL = ""; 
      Script = ""; 
     } 

     public override string ToString() 
     { 
      return Text; 
     } 

     private void NotifyPropertyChanged(string inf) 
     { 
      if (PropertyChanged != null) 
      { 
       PropertyChanged(this, new PropertyChangedEventArgs(inf)); 
      } 
     } 

     public event PropertyChangedEventHandler PropertyChanged; 
    } 


    private MenuItem mnuitm; 
    private MySqlConnection sqlcon; 

    public frmMenuItems() 
    { 
     InitializeComponent(); 
    } 

    private void btnClose_Click(object sender, EventArgs e) 
    { 
     this.Close(); 
    } 

    private void btnCancel_Click(object sender, EventArgs e) 
    { 
     mnuitm.Clear(); 
    } 

    private void frmMenuItems_Load(object sender, EventArgs e) 
    { 
     string constr = "server={0};uid={1};pwd={2};database={3};"; 
     DBItem dbi = CountyDataManager.CountyData.DBConnection; 
     constr = string.Format(constr, [MyHost], [MyUsername], [MyPassword], [MyDatabase]); 
     sqlcon = new MySqlConnection(constr); 
     sqlcon.Open(); 

     mnuitm = new MenuItem(); 
     SetBindings(); 
     RefreshList(); 
    } 

    private void SetBindings() 
    { 
     txtMenuText.DataBindings.Clear(); 
     txtURL.DataBindings.Clear(); 
     txtScript.DataBindings.Clear(); 

     txtMenuText.DataBindings.Add("Text", mnuitm, "Text"); 
     txtURL.DataBindings.Add("Text", mnuitm, "URL"); 
     txtScript.DataBindings.Add("Text", mnuitm, "Script"); 
    } 

    private void RefreshList() 
    { 
     using (MySqlCommand cmd = new MySqlCommand("SELECT `menuid`,`menutext`,`url`,`script` FROM tblindexmenu ORDER BY `menutext`", sqlcon)) 
     { 
      lstMenuItems.Items.Clear(); 
      using (MySqlDataReader rdr = cmd.ExecuteReader()) 
      { 
       while (rdr.Read()) 
       { 
        lstMenuItems.Items.Add(new MenuItem(Int32.Parse(rdr[0].ToString()), rdr[1].ToString(),rdr[2].ToString(),rdr[3].ToString())); 
       } 
      } 
     } 
    } 

    private void frmMenuItems_FormClosing(object sender, FormClosingEventArgs e) 
    { 
     sqlcon.Close(); 
    } 

    private void lstMenuItems_SelectedIndexChanged(object sender, EventArgs e) 
    { 
     if (lstMenuItems.SelectedIndex > -1) 
     { 
      mnuitm = (MenuItem)lstMenuItems.SelectedItem; 
     } 
    } 
} 

接收反馈后,我进行了如下修改:

新增的copyfrom()到菜单项

public void CopyFrom(MenuItem itm) 
{ 
    this.ID = itm.ID; 
    this.URL = itm.URL; 
    this.Text = itm.Text; 
    this.Script = itm.Script; 
} 

我然后修改的SelectedIndexChanged代码以使用新的功能

mnuitm.CopyFrom((MenuItem)lstMenuItems.SelectedItem); 

回答

0

这是设计。当你写

itm = (MyItem)cboMyItemsCombobox.SelectedItem; 

你没有改变任何使用指向菜单项itm的属性,而更改了菜单项itm点。您所需要的

一种选择是将一个函数添加MenuItem看起来像

SetFromOtherMenuItem(MenuItem other) 
{ 
    this.Url = other.Url 
    //etc 
} 

再次,PropertyChanged意味着一个财产上的一些实例已更改。在你的情况下,只有一个指向该实例的变量发生了变化(指向一个不同的实例)。

+0

谢谢,这个结果很好。虽然这是我想要避免的,但我无法赢得所有人。 – nclayton 2010-10-26 18:02:13

+0

不客气。你也可以坚持这个任务,并调用一个方法,比如说NotifyallProperties,它将简单地为所有的属性调用NotifyPropertyChanged – 2010-10-26 18:42:00