我有一个实现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);
谢谢,这个结果很好。虽然这是我想要避免的,但我无法赢得所有人。 – nclayton 2010-10-26 18:02:13
不客气。你也可以坚持这个任务,并调用一个方法,比如说NotifyallProperties,它将简单地为所有的属性调用NotifyPropertyChanged – 2010-10-26 18:42:00