问题
C# - .Net4.0, Visual Studio 2010
For certain reasons I'm using a separate class to store some of my custom control's properties (properties to do with drawing a grid). This is causing some problems, since I'd like to be able to call "Invalidate()" any time these values are edited (either via the properties window, or during run-time), to automatically redraw the control. The best solution I could think of was to implement INotifyPropertyChanged within my "GridProperties" class, fire off a PropertyChanged event any time the relevant "set" accessors are called, and then subscribe to the PropertyChanged event handler from my control class to call a "Redraw" method (which just calls Invalidate()).
Here's a shortened version of my code so far.
class MyControl : Control
{
[Browsable(true)]
public GridProperties Grid { get; set; }
public MyControl()
{
Grid = new GridValues();
Grid.Columns = 4;
Grid.Rows = 4;
Grid.ShowGridLines = true;
Grid.PropertyChanged += Redraw;
}
private void Redraw (object sender, PropertyChangedEventArgs e)
{
Invalidate();
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
//draw gridlines
//draw columns/ rows
}
}
class GridProperties : INotifyPropertyChanged
{
private int columns;
private int rows;
private bool showGridLines;
public int Columns
{
get { return columns; }
set
{
if (columns != value)
{
columns = value;
NotifyPropertyChanged("Columns");
}
}
}
public int Rows...
//same kinda deal for rows & showGridLines
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string info)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
What I expected: Redraw gets called any time Grid.Columns/ Grid.Rows/ Grid.ShowGridLines values are changed in any way (hopefully through properties window too).
What happens: Redraw never gets called, unless I do something like this, in an entirely new method in MyControl:
Grid.PropertyChanged += Redraw;
Grid.ShowGridLines = false;
This works during run-time, but this defeats the point of using an event manager since I can just set the values then call Invalidate every time, and it doesn't help with any changes made through the properties window.
If anyone could give me a heads up on what I'm doing wrong or whether there's a better way, I'd really appreciate it. In all honesty I'm not even sure whether subscribing to a member's event manager is good practice or not.
回答1:
Thanks to Gusman for the solution. Instead of hooking up to PropertyChanged from within MyControl's constructor, I just hooked up to it from within Grid's setter, like so:
private GridProperties grid;
[Browsale(true)]
public GridProperties Grid
{
get
{
return grid;
}
set
{
if(grid! = null)
grid.PropertyChanged -= Redraw;
grid = value;
grid.PropertyChanged += Redraw;
}
}
I can only assume something is replacing my GridProperties object somewhere. Either way, any time Grid's setter is accessed I just unhook/ and re-hook the PropertyChanged event manager, and now the screen updates whenever Grid's values are changed, whether by code or from the properties window.
回答2:
Try inserting this after the constructor MyControl():
protected override void OnCreateControl()
{
base.OnCreateControl();
grid.PropertyChanged += Redraw;
}
来源:https://stackoverflow.com/questions/37015016/c-sharp-custom-control-redraw-after-changing-a-member-objects-properties