Property Grid控件选中属性时UI闪烁问题求助
我在使用Property Grid + ComboBox组合时遇到过类似的闪烁问题,结合你的代码和描述,应该是控件重绘触发过于频繁或者双缓冲没开启导致的,下面给你几个针对性的解决方案:
问题回顾
根据ComboBox选中值切换PropertyGrid.SelectedObject并刷新后,编辑Property Grid属性时整个屏幕出现重绘闪烁,切出再切回后消失,且未手动编写过重绘函数。
补充的ComboBox切换代码
if (this.comboBoxHomerSelectSettings.SelectedItem.ToString() == "AppSettings") { this.comboBoxHomerSublist.Visible = false; this.propertyGridEditSettings.SelectedObject = Settings.SingleInstance.SettingsValues.AppSettings; } else if (this.comboBoxHomerSelectSettings.SelectedItem.ToString() == "WaferSpecificSettings") { this.comboBoxHomerSublist.Visible = true; this.comboBoxHomerSublist.Items.Clear(); for (int i = 0; i < Settings.SingleInstance.SettingsValues.WaferSpeicificSettingsList.WaferSpeicificInformationList.Count;i++ ) { this.comboBoxHomerSublist.Items.Add(Settings.SingleInstance.SettingsValues.WaferSpeicificSettingsList.WaferSpeicificInformationList.ElementAt(i)); } this.comboBoxHomerSublist.SelectedIndex = 0; this.propertyGridEditSettings.SelectedObject = this.comboBoxHomerSublist.SelectedItem; } else if (this.comboBoxHomerSelectSettings.SelectedItem.ToString() == "BinColorMapping") { this.comboBoxHomerSublist.Visible = true; this.comboBoxHomerSublist.Items.Clear(); for (int i = 0; i < Settings.SingleInstance.SettingsValues.BinColorInfoList.BinColorInformationList.Count; i++) { this.comboBoxHomerSublist.Items.Add(Settings.SingleInstance.SettingsValues.BinColorInfoList.BinColorInformationList.ElementAt(i)); } this.comboBoxHomerSublist.SelectedIndex = 0; this.propertyGridEditSettings.SelectedObject = this.comboBoxHomerSublist.SelectedItem; } else if (this.comboBoxHomerSelectSettings.SelectedItem.ToString() == "CommonSettings") { this.comboBoxHomerSublist.Visible = false; this.propertyGridEditSettings.SelectedObject = Settings.SingleInstance.SettingsValues.CommonSettings; } else if (this.comboBoxHomerSelectSettings.SelectedItem.ToString() == "DOETypeMapping") { this.comboBoxHomerSublist.Visible = true; this.comboBoxHomerSublist.Items.Clear(); for (int i = 0; i < Settings.SingleInstance.SettingsValues.DOETypeMapingInfoList.DOETypeMapingInformationList.Count; i++) { this.comboBoxHomerSublist.Items.Add(Settings.SingleInstance.SettingsValues.DOETypeMapingInfoList.DOETypeMapingInformationList.ElementAt(i)); } this.comboBoxHomerSublist.SelectedIndex = 0; this.propertyGridEditSettings.SelectedObject = this.comboBoxHomerSublist.SelectedItem; } this.propertyGridEditSettings.Refresh();
具体解决方案
1. 给PropertyGrid开启双缓冲
WinForms原生PropertyGrid默认没开启双缓冲,这是导致重绘闪烁的常见原因。你可以自定义一个继承自PropertyGrid的控件,强制开启双缓冲:
public class BufferedPropertyGrid : PropertyGrid { protected override CreateParams CreateParams { get { CreateParams cp = base.CreateParams; cp.ExStyle |= 0x02000000; // 启用WS_EX_COMPOSITED样式,实现双缓冲 return cp; } } }
然后把窗体上的propertyGridEditSettings替换成这个自定义控件,基本能解决大部分重绘闪烁问题。
2. 去掉不必要的Refresh调用
看你代码最后手动调用了propertyGridEditSettings.Refresh(),其实当你设置SelectedObject时,PropertyGrid会自动触发刷新,额外的Refresh会导致重复重绘,加重闪烁。直接删掉这行代码试试。
3. 批量更新控件状态,减少重绘次数
在切换ComboBox选项时,你同时修改了子ComboBox的可见性、Items集合,还设置了PropertyGrid的SelectedObject,这些操作会多次触发界面重绘。可以把这些操作包裹在SuspendLayout()和ResumeLayout()之间,让所有变更一次性生效:
this.SuspendLayout(); // 暂停布局更新 // 原来的所有判断逻辑代码... // 去掉this.propertyGridEditSettings.Refresh(); this.ResumeLayout(false); // 恢复布局,一次性更新界面
这样能避免多次局部重绘导致的闪烁。
4. 给Settings类实现INotifyPropertyChanged接口
如果你的Settings相关类没有实现这个接口,当你在PropertyGrid里编辑属性时,控件无法感知到具体哪个属性变化,只能整个重绘。实现接口后,PropertyGrid只会重绘修改的属性区域,大大减少闪烁:
public class AppSettings : INotifyPropertyChanged { private string _exampleProperty; public string ExampleProperty { get => _exampleProperty; set { if (_exampleProperty != value) { _exampleProperty = value; OnPropertyChanged(nameof(ExampleProperty)); } } } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
把所有需要在PropertyGrid中编辑的Settings类都加上这个实现。
内容的提问来源于stack exchange,提问作者Athul Raj

