WPF 从父级覆盖 IsEnabled
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22248943/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
WPF override IsEnabled from Parent
提问by LionAM
I just searched for a way to enable a child control while the parent control has IsEnabled = false.
All answers that I have found up to now say that it is not possible - one has to enable the parent and disable the child controls except the ones that should still be enabled.
我只是寻找一种方法来启用子控件而父控件具有IsEnabled = false. 到目前为止,我找到的所有答案都说这是不可能的 - 必须启用父控件并禁用子控件,但仍应启用的控件除外。
However, by overriding the Metadata for the IsEnabledProperty in the App.xaml.cs file, I was able to change this default behavior:
但是,通过覆盖 App.xaml.cs 文件中 IsEnabledProperty 的元数据,我能够更改此默认行为:
protected override void OnStartup(StartupEventArgs e)
{
UIElement.IsEnabledProperty.OverrideMetadata(typeof(FrameworkElement),
new UIPropertyMetadata(true,IsEnabledChanged, CoerceIsEnabled));
}
private void IsEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var childrenCount = VisualTreeHelper.GetChildrenCount(d);
for (int i = 0; i < childrenCount; ++i)
{
var child = VisualTreeHelper.GetChild(d, i);
child.CoerceValue(UIElement.IsEnabledProperty);
}
}
private object CoerceIsEnabled(DependencyObject d, object basevalue)
{
var parent = VisualTreeHelper.GetParent(d) as FrameworkElement;
if (parent != null && parent.IsEnabled == false)
{
if (d.ReadLocalValue(UIElement.IsEnabledProperty) == DependencyProperty.UnsetValue)
{
return false;
}
}
return basevalue;
}
Now you can manually set the IsEnabledproperty on a child, which overrides the parent value.
现在您可以手动设置子项的IsEnabled属性,该属性会覆盖父项值。
Are there any drawbacks of this approach?
这种方法有什么缺点吗?
回答by user1568891
This worked for my situation on a control used several times with some slight modifications.
这适用于我多次使用的控件的情况,并稍作修改。
Placing here to help any future web searchers in a similar situation:
放在这里是为了帮助未来遇到类似情况的网络搜索者:
- placed it in a static constructor instead of an event, otherwise it tried to set it multiple times and threw a "PropertyMetadata is already registered for type '{type}'." exception.
- Changed the type to match the control
- 将其放置在静态构造函数而不是事件中,否则它尝试多次设置它并抛出“PropertyMetadata 已为类型 '{type}' 注册”。例外。
- 更改了类型以匹配控件
Code:
代码:
Make sure to find and replace [CustomControl]with the type name of your control.
确保找到并替换[CustomControl]为您的控件的类型名称。
static [CustomControl]()
{
UIElement.IsEnabledProperty.OverrideMetadata(typeof([CustomControl]), new UIPropertyMetadata(true, [CustomControl]_IsEnabledChanged, CoerceIsEnabled));
}
private static void [CustomControl]_IsEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var childrenCount = VisualTreeHelper.GetChildrenCount(d);
for (int i = 0; i < childrenCount; ++i)
{
var child = VisualTreeHelper.GetChild(d, i);
child.CoerceValue(UIElement.IsEnabledProperty);
}
}
private static object CoerceIsEnabled(DependencyObject d, object basevalue)
{
var parent = VisualTreeHelper.GetParent(d) as FrameworkElement;
if (parent != null && parent.IsEnabled == false)
{
if (d.ReadLocalValue(UIElement.IsEnabledProperty) == DependencyProperty.UnsetValue)
{
return false;
}
}
return basevalue;
}
回答by Eric
Another option is to override the FrameworkPropertyMetadataOptions to remove the Inherits property. I had a similar problem with the FontSize and this worked well:
另一种选择是覆盖 FrameworkPropertyMetadataOptions 以删除 Inherits 属性。我在 FontSize 上遇到了类似的问题,并且效果很好:
FontSizeProperty.OverrideMetadata(
typeof(YourControl),
new FrameworkPropertyMetadata(8.0,
FrameworkPropertyMetadataOptions.None, changed));
回答by eldor
The drawback is at least, that you break the basic concept, and the IsEnabled is not used for the intended scope. This workaround also makes maintenance a bit more complex (the developer has to understand first, why it works differently).
缺点至少是,您打破了基本概念,并且 IsEnabled 未用于预期范围。这种变通方法也使维护变得更加复杂(开发人员必须首先了解为什么它的工作方式不同)。
As it is suggested in comments, I would say, that a redesign of this window would help. Especially, if I would like to forbid only the editing (data modification) in the form, I would use other properties like IsReadOnly.
正如评论中所建议的那样,我想说,重新设计这个窗口会有所帮助。特别是,如果我只想禁止表单中的编辑(数据修改),我会使用其他属性,如 IsReadOnly。

