2016-05-03 3 views
0

C# - .Net4.0, Visual Studio 2010C# пользовательский элемент управления - Перерисовка после изменения свойств объекта-члена

По некоторым причинам я использую отдельный класс для хранения некоторых свойств моего пользовательского элемента управления (свойства, чтобы сделать с рисованием сетки). Это вызывает некоторые проблемы, так как я хотел бы иметь возможность вызывать «Invalidate()» в любое время, когда эти значения редактируются (либо через окно свойств, либо во время выполнения), чтобы автоматически перерисовывать элемент управления. Лучшее решение, которое я мог придумать, это реализовать INotifyPropertyChanged в моем классе «GridProperties», отключить событие PropertyChanged в любое время, когда вызываются соответствующие «set» accessors, а затем подписаться на обработчик события PropertyChanged из моего класса управления, чтобы вызвать « 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)); 
    } 
} 

Что я ожидал: Redraw вызывается в любое время Grid.Columns/Grid.Rows/Grid.ShowGridLines значения изменяются в любом случае (надеюсь, через окно свойств тоже).

Что происходит: не перерисовывать никогда не вызывается, если я не делаю что-то вроде этого, в совершенно новом методе в MyControl:

Grid.PropertyChanged += Redraw; 
Grid.ShowGridLines = false; 

Это работает во время выполнения, но это побеждает точку, используя событие менеджером, так как я могу просто установить значения, а затем вызвать Invalidate каждый раз, и это не поможет с любыми изменениями, внесенными в окно свойств.

Если бы кто-нибудь мог дать мне понять, что я делаю неправильно, или есть лучший способ, я бы очень признателен. Честно говоря, я даже не уверен, что подписка на управляющий событиями участника - хорошая практика или нет.

+0

Хм, может быть, ваше свойство Grid заменяется? Если свойство должно быть разрешено полностью воссоздать, а затем на вашем сеттере, вы должны подключиться к событию PropertyChanged (также отцепите предыдущий экземпляр GridProperties), иначе удалите setter для проблем aviod (вы можете использовать инициализаторы свойств для C# 6.0 или private seters для предыдущих версий). – Gusman

+0

Я предполагаю, что ты прав; Я сделал то, что вы рекомендовали, и подключил событие PropertyChanged из сеттера Set Grid, и теперь он работает отлично. Было странно, потому что я не думал, что я явно заменяю Grid (кроме встроенного конструктора MyControl для его инициализации), но в любом случае рад, что он работает сейчас! Благодарю. – 9bjames

+0

Рад, что он работает. Очень возможно, что дизайнер заменяет ваш GridProperties, вы можете проверить файл .designer.cs, должно быть задание. – Gusman

ответ

1

Благодаря Gusman для решения. Вместо подключения к PropertyChanged внутри конструктора MyControl, я просто подключил к нему изнутри сеттеру в управляющей сетке в радиолампе, например, так:

private GridProperties grid; 
[Browsale(true)] 
public GridProperties Grid 
{ 
    get 
    { 
     return grid; 
    } 
    set 
    { 
     if(grid! = null) 
      grid.PropertyChanged -= Redraw; 

     grid = value; 
     grid.PropertyChanged += Redraw; 
    } 
} 

Я могу только предположить, что что-то меняет мой GridProperties объект где-нибудь. В любом случае, в любое время, когда меняет сеттер сетки, я просто отцепляю/и снова затягиваю диспетчер событий PropertyChanged, и теперь экран обновляется всякий раз, когда значения Grid изменяются, будь то кодом или из окна свойств.

Смежные вопросы