我需要我的控件从Grid类型的祖先继承UIElement.IsEnabledProperty(可选Window或任何其他我可以用我的网格包裹的元素)
CS:下面我覆盖了UIElement.IsEnabledProperty的元数据,并使用Change和Coerce委托进行设置。
static PipeControl()
{
PipeControl.IsEnabledProperty.OverrideMetadata(typeof(PipeControl), new FrameworkPropertyMetadata(false, OnIsEnabledPropertyChanged, OnIsEnabledPropertyCoerce));
}
private static void OnIsEnabledPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var isEnabled = (bool)e.NewValue;
}
private static object OnIsEnabledPropertyCoerce(DependencyObject d, object baseValue)
{
var valueSource = DependencyPropertyHelper.GetValueSource(d, PipeControl.IsEnabledProperty);
var pipeContorl = d as PipeControl;
if (pipeContorl == null) return baseValue;
return (bool)baseValue && pipeContorl.IsMyPipe;
}
XAML:
<Grid IsEnabled="{Binding IsMyCondition , Mode=OneWay}">
<game:PipeControl Grid.Row="2" />
<game:PipeControl Grid.Row="2" Grid.Column="1" />
</Grid>
每次IsMyCondition更改OnIsEnabledPropertyCoerce在每个PipeContorl中调用, 永远不会调用OnIsEnabledPropertyChanged, OnIsEnabledProerty中的ValueSource Coerce为“Default”(显示Coerce始终获取默认的false值)。
我必须以我需要使用继承的方式错过某些东西, 我希望价值来源是“继承” 和要调用的OnIsEnabledPropertyChanged。
答案 0 :(得分:4)
UIElement有一个虚拟属性IsEnabledCore,它应该(?)用于强制IsEnabled属性。例如,这就是Button或MenuItem强制IsEnabled属性的方式,具体取决于它们的CanExecute属性。 在自定义控件中,您可以将属性覆盖为:
protected override bool IsEnabledCore
{
get
{
return ( base.IsEnabledCore && IsMyPipe );
}
}
重要的是当IsEnabled所依赖的任何属性(例如IsMyPipe)发生变化时调用CoerceValue。
因此自定义控件实现将是:
static PipeControl()
{
DefaultStyleKeyProperty.OverrideMetadata( typeof( PipeControl ), new FrameworkPropertyMetadata( typeof( PipeControl ) ) );
}
public bool IsMyPipe
{
get { return ( bool )GetValue( IsMyPipeProperty ); }
set { SetValue( IsMyPipeProperty, value ); }
}
public static readonly DependencyProperty IsMyPipeProperty =
DependencyProperty.Register(
"IsMyPipe",
typeof( bool ),
typeof( UIElement ),
new PropertyMetadata(
true,
new PropertyChangedCallback( OnIsMyPipeChanged ) ) );
private static void OnIsMyPipeChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
{
d.CoerceValue( UIElement.IsEnabledProperty );
}
希望这会有所帮助,对此解决方案的任何评论都非常受欢迎。
答案 1 :(得分:2)
上面有Adnan的答案,答案是:
How can I add logic to an existing dependency-property callback?
我写了一个完整的答案。
CS:
static PipeControl()
{
PipeControl.IsEnabledProperty.OverrideMetadata(typeof(PipeControl), new UIPropertyMetadata(new PropertyChangedCallback(OnIsEnabledPropertyChanged)));
}
private static void OnIsEnabledPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var isEnabled = (bool)e.NewValue;
}
protected override bool IsEnabledCore
{
get
{
return (base.IsEnabledCore && IsMyPipe);
}
}
IsEnabledCore将值返回给Callback,因此强制在那里发生, 然后是CallBack。
仅供参考,设置本地默认值似乎会覆盖继承,因此如果覆盖一个Inherited 属性的元数据确实给出了一个默认的本地值,如下所示:
PipeControl.IsEnabledProperty.OverrideMetadata(typeof(PipeControl), new UIPropertyMetadata(false,new PropertyChangedCallback(OnIsEnabledPropertyChanged)));
另外,如果你只需要添加强制逻辑,你可以覆盖IsEnabledCore, 并且对IsEnabledProperty的元数据不做任何其他操作。