8

Tôi có một ứng dụng Winform sử dụng màu sắc để làm nổi bật những thứ nhất định. Tôi muốn cho phép người dùng thay đổi màu 'của họ'. Như một bài tập, tôi nghĩ rằng tôi sẽ tạo ra một thể hiện của một lớp, với các thuộc tính cho màu sắc, và gán nó vào một lưới thuộc tính (để có được một trình soạn thảo đẹp).PropertyGrid không nhận thấy các thuộc tính thay đổi trong mã?

Điều này có vẻ hoạt động tốt, nhưng sau đó tôi nghĩ rằng tôi muốn cho phép người dùng đặt lại màu (sau khi họ đã không sử dụng và đặt chúng thành 20 màu be). Vì vậy, tôi đã thêm nút "đặt lại" vào biểu mẫu của tôi, đặt thuộc tính màu của đối tượng của tôi về giá trị mặc định.

Tuy nhiên, có vẻ như trong khi nó đặt thuộc tính của đối tượng của tôi trở lại, lưới thuộc tính không thay đổi. Nếu, sau khi đặt lại, tôi làm lưới thuộc tính "Làm mới", nó có màu thiết lập lại.

Tôi giả định rằng lưới thuộc tính không biết rằng đối tượng cơ bản đã bị thay đổi?

Có điều gì thiếu trong trường hợp này hay tôi chỉ chấp nhận và gọi phương thức Làm mới khi đặt lại đối tượng của mình?

Cảm ơn

(rất giống câu hỏi here)

public partial class Form1 : Form 
{ 
    public Form1() 
    { 
    InitializeComponent(); 

    this.propertyGrid1.SelectedObject = new Colours(); 
    } 

    private void button1_Click(object sender, EventArgs e) 
    { 
    Colours colours = this.propertyGrid1.SelectedObject as Colours; 
    colours.Reset(); 
    } 
} 

public partial class Colours : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 

    public Color ColourP1 { get; set; } 

    public void Reset() 
    { 
    this.ColourP1 = Color.Red; 
    var handler = this.PropertyChanged; 
    if (handler != null) handler(this, new PropertyChangedEventArgs("ColourP1")); 
    } 
} 

Sau ngày từ bình luận của tôi về "không có gì đặt mua các INotifyPropertyChanged.PropertyChanged", nhược điểm trong subsclassing là những gì điều khiển PropertyGrid sao cho nó hoạt động?

public partial class MyPropertyGrid : System.Windows.Forms.PropertyGrid 
{ 
    private INotifyPropertyChanged _selectedObject; 

    protected override void OnSelectedObjectsChanged(EventArgs e) 
    { 
    base.OnSelectedObjectsChanged(e); 

    if (_selectedObject != null) _selectedObject.PropertyChanged -= selectedObject_PropertyChanged; 
    _selectedObject = this.SelectedObject as INotifyPropertyChanged; 
    if (_selectedObject != null) _selectedObject.PropertyChanged += selectedObject_PropertyChanged; 
    } 

    private void selectedObject_PropertyChanged(object sender, PropertyChangedEventArgs e) 
    { 
    this.Refresh(); 
    } 
} 

Trả lời

9

Để trả lời câu hỏi của bạn về lý do PropertyGrid không thay đổi, tài liệu MSDN cho PropertyGrid nói điều này:

Thông tin được hiển thị trong lưới là ảnh chụp nhanh thuộc tính tại thời điểm đối tượng được chỉ định. Nếu giá trị thuộc tính của đối tượng được chỉ định bởi SelectedObject được thay đổi trong mã tại thời gian chạy, thì giá trị mới sẽ không được hiển thị cho đến khi một hành động được thực hiện trong lưới mà làm cho lưới làm mới.

Vì vậy, có vẻ như PropertyGrid không phải là điều khiển tự động cập nhật. Tôi nghĩ rằng đầu mối cho điều này là PropertyGrid sử dụng phương pháp SelectedObject thay vì một phương pháp DataSource, và sau này có nghĩa là nó có thể lắng nghe INotifyPropertyChanged.

Bạn còn lại với những gì LarsTech đã đề xuất và làm mới lưới theo cách thủ công.

+0

Vâng, có khá nhiều tiền. – LarsTech

6

Chỉ cần cố gắng làm mới nó:

private void button1_Click(object sender, EventArgs e) 
{ 
    Colours colours = this.propertyGrid1.SelectedObject as Colours; 
    colours.Reset(); 
    this.propertyGrid1.Refresh(); 
} 

Giả sử bạn sẽ có nhiều tài sản, bạn có thể sử dụng sự kiện PropertyChanged của bạn. Tôi sẽ sửa đổi lớp màu của bạn như thế này:

public class Colours : INotifyPropertyChanged { 
    public event PropertyChangedEventHandler PropertyChanged; 

    private Color _ColourP1; 

    public void Reset() { 
    this.ColourP1 = Color.Red; 
    } 

    private void OnChanged(string propName) { 
    if (PropertyChanged != null) 
     PropertyChanged(this, new PropertyChangedEventArgs(propName)); 
    } 

    public Color ColourP1 { 
    get { return _ColourP1; } 
    set { 
     _ColourP1 = value; 
     OnChanged("ColourP1"); 
    } 
    } 
} 

Sau đó, hình thức của bạn sẽ trông như thế này:

public Form1() { 
    InitializeComponent(); 

    Colours colours = new Colours(); 
    colours.PropertyChanged += colours_PropertyChanged; 
    this.propertyGrid1.SelectedObject = colours; 
} 

private void colours_PropertyChanged(object sender, PropertyChangedEventArgs e) { 
    this.propertyGrid1.Refresh(); 
} 

private void button1_Click(object sender, EventArgs e) { 
    ((Colours)this.propertyGrid1.SelectedObject).Reset(); 
} 
+0

Hi, cảm ơn, đó là khá nhiều những gì tôi đã có rồi. Tôi đã quan tâm nhiều hơn lý do tại sao lưới điện bất động sản không nhận thấy rằng tài sản đã thay đổi. Không có gì (ví dụ: điều khiển PropertyGrid) đăng ký với sự kiện "PropertyChanged". Chắc chắn ... tôi có thể tự mình làm như bạn có, nhưng tại sao? Có thể là điều khiển PropertyGrid không có thuộc tính bị ràng buộc, do đó, không lắng nghe sự kiện INotifyPropertyChanged? –

4

Đã xảy ra trong câu hỏi này khi cố nhớ những gì tôi đã từng sử dụng và nghĩ rằng nó có thể hữu ích cho người khác.

Bạn có thể sử dụng thuộc tính [RefreshProperties] để kích hoạt cập nhật cho lưới thuộc tính.

ví dụ:

[RefreshProperties(RefreshProperties.All)] 
    public int MyProperty{ get; set; }