我在这里看到这个问题很多,但它总是WPF,我使用的是WinForms。
我有一个实现INotifyPropertyChanged的类,当在其中一个属性setter中调用OnPropertyChanged时,PropertyChanged事件对象始终为null,因此永远不会引发该事件。
public abstract class ProxyScraperSiteBase : IProxyScraperSite, INotifyPropertyChanged
{
private int scrapedCount;
public event PropertyChangedEventHandler PropertyChanged;
public event EventHandler<PageScrapedEventArgs> PageScraped;
public string SiteName { get; set; }
public List<Proxy> ScrapedProxies { get; set; } = new List<Proxy>();
public int ScrapedCount {
get
{
return this.scrapedCount;
}
set
{
this.scrapedCount = value;
OnPropertyChanged();
}
}
public abstract Task ScrapeAsync(IWebDriver driver, PauseOrCancelToken pct = null);
private void OnPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
protected void OnPageScraped(List<Proxy> proxies)
{
if (PageScraped != null)
{
PageScraped(this, new PageScrapedEventArgs(proxies));
}
}
}
设置绑定
public partial class ProxyScraperForm : Form
{
private BindingList<IProxyScraperSite> sites = new BindingList<IProxyScraperSite>();
public ProxyScraperForm()
{
InitializeComponent();
sites.Add(new ProxyScraperSiteUsProxyOrg());
ScraperDataGridView.DataSource = sites;
}
private void ScrapeButton_Click(object sender, EventArgs e)
{
foreach (var site in sites)
{
Task.Run(async () =>
{
site.PageScraped += Site_PageScraped;
var driver = SeleniumUtility.CreateDefaultFirefoxDriver();
await site.ScrapeAsync(driver);
driver.Quit();
});
}
}
private void Site_PageScraped(object sender, PageScrapedEventArgs e)
{
ScraperDataGridView.BeginInvoke(new Action(() =>
{
((IProxyScraperSite)sender).ScrapedCount += e.Proxies.Count;
}));
}
}
答案 0 :(得分:2)
问题是您绑定到IProxyScraperSite
,但该接口未实现INotifyPropertyChanged
。绑定只知道接口而不是具体类,所以它不知道INotifyPropertyChanged
已经实现。修复很简单,将INotifyPropertyChanged
移到IProxyScraperSite
界面:
public interface IProxyScraperSite : INotifyPropertyChanged
{
...
}
这将允许您的BindingList
订阅INotifyPropertyChanged
事件,因为它现在可以看到绑定对象实现它。