依赖属性继承

era*_*zap 2 wpf inheritance dependency-properties custom-controls

我需要我的控件从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;
    }
Run Code Online (Sandbox Code Playgroud)

XAML:

    <Grid IsEnabled="{Binding IsMyCondition , Mode=OneWay}">        
         <game:PipeControl Grid.Row="2"  />            
         <game:PipeControl  Grid.Row="2" Grid.Column="1" />
    </Grid> 
Run Code Online (Sandbox Code Playgroud)

每次IsMyCondition更改时,每个PipeContorl中都会调用一次OnIsEnabledPropertyCoerce,从不调用OnIsEnabledPropertyChanged,OnIsEnabledProerty Coerce中的ValueSource为“ Default”(显示Coerce始终获取默认的假值)。

我必须以需要使用继承的方式错过某些东西,我希望值源被“继承”,并调用OnIsEnabledPropertyChanged。

小智 5

UIElement具有一个虚拟属性IsEnabledCore,应使用该属性强制IsEnabled属性。例如,这就是Button或MenuItem强制IsEnabled属性取决于其CanExecute属性的方式。在自定义控件中,您可以按以下方式覆盖属性:

    protected override bool IsEnabledCore
    {
        get
        {
            return ( base.IsEnabledCore && IsMyPipe );
        }
    }
Run Code Online (Sandbox Code Playgroud)

重要的是,当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 );
    }
Run Code Online (Sandbox Code Playgroud)

希望这会有所帮助,并且欢迎对该解决方案发表任何评论。