我看到这个问题在这里问很多,但是它总是WPF,我正在使用winforms。
我有一个实现InotifyPropertychanged的类,当onPropertychanged在其中一个属性设置器中调用时,属性变化的事件对象始终是无效的,因此事件永远不会增加。
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;
}));
}
}
问题是您要绑定到IProxyScraperSite
,但是该接口不实现INotifyPropertyChanged
。绑定仅知道接口,而不是具体类,因此不知道已经实现了INotifyPropertyChanged
。修复程序很简单,将INotifyPropertyChanged
移至IProxyScraperSite
接口:
public interface IProxyScraperSite : INotifyPropertyChanged
{
...
}
这将允许您的BindingList
订阅INotifyPropertyChanged
事件,因为它现在可以看到绑定的对象实现它。