C# 自定义控件 - 更改成员对象的属性后重绘
C# custom control - Redraw after changing a member object's properties
C#-.Net4.0,Visual Studio2010
出于某些原因,我使用单独的 class 来存储我的一些自定义控件的属性(与绘制网格有关的属性)。这导致了一些问题,因为我希望能够在编辑这些值时随时调用 "Invalidate()"(通过属性 window,或在 运行 期间),以自动重绘控件。我能想到的最佳解决方案是在我的 "GridProperties" class 中实现 INotifyPropertyChanged,在调用相关 "set" 访问器时触发 PropertyChanged 事件,然后订阅 PropertyChanged 事件处理程序从我的控件 class 调用 "Redraw" 方法(只调用 Invalidate()).
到目前为止,这是我的代码的简化版本。
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));
}
}
我所期望的:任何时候都会调用重绘 Grid.Columns/ Grid.Rows/ Grid.ShowGridLines 值以任何方式更改(希望也通过属性 window)。
会发生什么:Redraw 永远不会被调用,除非我在 MyControl 中用一个全新的方法做这样的事情:
Grid.PropertyChanged += Redraw;
Grid.ShowGridLines = false;
这在 运行 时间内有效,但这违背了使用事件管理器的意义,因为我每次都可以设置值然后调用 Invalidate,并且它对通过属性 window.
如果有人能提醒我我做错了什么或者是否有更好的方法,我将不胜感激。老实说,我什至不确定订阅会员的活动管理器是否是一种好的做法。
感谢 Gusman 提供的解决方案。我没有从 MyControl 的构造函数中连接到 PropertyChanged,而是从 Grid 的 setter 中连接到它,如下所示:
private GridProperties grid;
[Browsale(true)]
public GridProperties Grid
{
get
{
return grid;
}
set
{
if(grid! = null)
grid.PropertyChanged -= Redraw;
grid = value;
grid.PropertyChanged += Redraw;
}
}
我只能假设某些东西正在某处替换我的 GridProperties 对象。无论哪种方式,只要 Grid 的 setter 被访问,我只需取消挂钩/重新挂钩 PropertyChanged 事件管理器,现在只要 Grid 的值发生变化,屏幕就会更新,无论是通过代码还是从属性 window。
尝试在构造函数 MyControl() 之后插入:
protected override void OnCreateControl()
{
base.OnCreateControl();
grid.PropertyChanged += Redraw;
}
C#-.Net4.0,Visual Studio2010
出于某些原因,我使用单独的 class 来存储我的一些自定义控件的属性(与绘制网格有关的属性)。这导致了一些问题,因为我希望能够在编辑这些值时随时调用 "Invalidate()"(通过属性 window,或在 运行 期间),以自动重绘控件。我能想到的最佳解决方案是在我的 "GridProperties" class 中实现 INotifyPropertyChanged,在调用相关 "set" 访问器时触发 PropertyChanged 事件,然后订阅 PropertyChanged 事件处理程序从我的控件 class 调用 "Redraw" 方法(只调用 Invalidate()).
到目前为止,这是我的代码的简化版本。
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));
}
}
我所期望的:任何时候都会调用重绘 Grid.Columns/ Grid.Rows/ Grid.ShowGridLines 值以任何方式更改(希望也通过属性 window)。
会发生什么:Redraw 永远不会被调用,除非我在 MyControl 中用一个全新的方法做这样的事情:
Grid.PropertyChanged += Redraw;
Grid.ShowGridLines = false;
这在 运行 时间内有效,但这违背了使用事件管理器的意义,因为我每次都可以设置值然后调用 Invalidate,并且它对通过属性 window.
如果有人能提醒我我做错了什么或者是否有更好的方法,我将不胜感激。老实说,我什至不确定订阅会员的活动管理器是否是一种好的做法。
感谢 Gusman 提供的解决方案。我没有从 MyControl 的构造函数中连接到 PropertyChanged,而是从 Grid 的 setter 中连接到它,如下所示:
private GridProperties grid;
[Browsale(true)]
public GridProperties Grid
{
get
{
return grid;
}
set
{
if(grid! = null)
grid.PropertyChanged -= Redraw;
grid = value;
grid.PropertyChanged += Redraw;
}
}
我只能假设某些东西正在某处替换我的 GridProperties 对象。无论哪种方式,只要 Grid 的 setter 被访问,我只需取消挂钩/重新挂钩 PropertyChanged 事件管理器,现在只要 Grid 的值发生变化,屏幕就会更新,无论是通过代码还是从属性 window。
尝试在构造函数 MyControl() 之后插入:
protected override void OnCreateControl()
{
base.OnCreateControl();
grid.PropertyChanged += Redraw;
}