编辑多个对象时属性在propertyGrid中的C#条件外观
本文关键字:中的 propertyGrid 条件 外观 属性 对象 编辑 | 更新日期: 2023-09-27 18:29:29
刚刚偶然发现了propertyGrid及其强大功能!然而,我有一项任务,我找不到如何处理它:
我有一个有类型的类。根据类型,它具有不同的可用属性。为了简单起见,我将它保存在一个类中(而不是多个继承类)(有十种类型,但它们大多具有相同的属性)。
例如,我有一个类MapObject,它的字符串类型可以等于"播放器"或"敌人"。对于"敌人",使用属性"名称",但对于"玩家",属性为空(未使用)。
当我选择两个对象时,其中一个是类型"玩家",另一个是"敌人",我希望属性"名称"只对"敌人"计数"。因此,我希望propertyGrid显示type="敌人"的对象的名称,当它(名称属性)在Grid中更改时,只将其分配给"敌人"类型的对象。
这样做可能吗?
根据您正在使用的PropertyGrid,切换可浏览属性可能会达到您想要的效果。关于如何在运行时做到这一点,请参阅我的答案。
如果像我一样使用Xceed PropertyGrid,那么在加载控件后仅在运行时更改Browseable属性不会有任何作用。相反,我还必须修改PropertyDefinitions集合。这里有一个扩展方法:
/// <summary>
/// Show (or hide) a property within the property grid.
/// Note: if you want to initially hide the property, it may be
/// easiest to set the Browable attribute of the property to false.
/// </summary>
/// <param name="pg">The PropertyGrid on which to operate</param>
/// <param name="property">The name of the property to show or hide</param>
/// <param name="show">Set to true to show and false to hide</param>
public static void ShowProperty(this PropertyGrid pg, string property, bool show)
{
int foundAt = -1;
for (int i=0; i < pg.PropertyDefinitions.Count; ++i)
{
var prop = pg.PropertyDefinitions[i];
if (prop.Name == property)
{
foundAt = i;
break;
}
}
if (foundAt == -1)
{
if (show)
{
pg.PropertyDefinitions.Add(
new Xceed.Wpf.Toolkit.PropertyGrid.PropertyDefinition()
{
Name = property,
}
);
}
}
else
{
if (!show)
{
pg.PropertyDefinitions.RemoveAt(foundAt);
}
}
}
如果以上内容不适用于您,那么以下内容可能会更好、更简单。它也没有像上面的代码那样使用不推荐使用的属性。。。
public static void ShowProperty(this PropertyGrid pg, string property, bool show)
{
for (int i = 0; i < pg.Properties.Count; ++i)
{
PropertyItem prop = pg.Properties[i] as PropertyItem;
if (prop.PropertyName == property)
{
prop.Visibility = show ? System.Windows.Visibility.Visible : System.Windows.Visibility.Collapsed;
break;
}
}
}
这是一种称为状态模式的设计模式。它很容易实现,而且不需要属性网格。http://www.dofactory.com/Patterns/PatternState.aspx
我用自己的自定义属性:
public class VisibilityAttribute : Attribute
{
public bool IsVisible { get; set; }
public VisibilityAttribute(bool isVisible)
{
IsVisible = isVisible;
}
}
然后我的数据模型:
public abstract class BaseSettings: INotifyPropertyChanged
{
public void SetVisibilityProperty(string propertyName, bool isVisible)
{
var theDescriptor = TypeDescriptor.GetProperties(this.GetType())[propertyName];
var theDescriptorVisibilityAttribute = (VisibilityAttribute)theDescriptor.Attributes[typeof(VisibilityAttribute)];
if (theDescriptorVisibilityAttribute == null) return;
theDescriptorVisibilityAttribute.IsVisible = isVisible;
}
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
public class ThrottleSettings : BaseSettings
{
private ThrottleType _throttleType = ThrottleType.SmartThrottle;
[PropertyOrder(1)]
public ThrottleType ThrottleType
{
get
{
return _throttleType;
}
set
{
if (value == ThrottleType.FullThrottle)
{
SetVisibilityProperty(nameof(FullThrottleTimeInMilliseconds), true);
SetVisibilityProperty(nameof(ThumbnailThrottleTimeInMilliseconds), false);
}
else if (value == ThrottleType.SmartThrottle)
{
SetVisibilityProperty(nameof(FullThrottleTimeInMilliseconds), false);
SetVisibilityProperty(nameof(ThumbnailThrottleTimeInMilliseconds), true);
}
else if (value == ThrottleType.NoThrottle)
{
SetVisibilityProperty(nameof(FullThrottleTimeInMilliseconds), false);
SetVisibilityProperty(nameof(ThumbnailThrottleTimeInMilliseconds), false);
}
_throttleType = value;
}
}
private int _fullThrottleTime = 100;
[PropertyOrder(2)]
[Visibility(false)]
[Description("Specifies full throttle time (in milliseconds).")]
public int FullThrottleTimeInMilliseconds
{
get
{
return _fullThrottleTime;
}
set
{
if (value < 0) return;
_fullThrottleTime = value;
}
}
private int _thumbnailThrottleTime = 0;
[PropertyOrder(3)]
[Visibility(true)]
[Description("Specifies thumbnail throttle time (in milliseconds).")]
public int ThumbnailThrottleTimeInMilliseconds
{
get
{
return _thumbnailThrottleTime;
}
set
{
if (value < 0) return;
_thumbnailThrottleTime = value;
}
}
}
最后,我订阅了"propertyGrid_PropertyValueChanged"事件,并在那里调用我的方法:
private void _propertyGrid_PropertyValueChanged(object sender, PropertyValueChangedEventArgs e)
{
RefreshVisibility(_propertyGrid.Properties);
}
这是方法本身:
private void RefreshVisibility(IList properties)
{
foreach (PropertyItem property in properties)
{
var visibilityAttribute = GetVisibilityAttribute(property);
if (visibilityAttribute != null)
{
if (visibilityAttribute.IsVisible)
property.Visibility = Visibility.Visible;
else
property.Visibility = Visibility.Collapsed;
}
RefreshVisibility(property.Properties);
}
}