Home > OS >  Using custom dependency property in style
Using custom dependency property in style

Time:07-08

I have a custom button control with a custom property IsPlaying.

internal class PlayPauseButton : Button
{
    public bool IsPlaying
    {
        get => (bool)GetValue(IsPlayingProperty);
        set => SetValue(IsPlayingProperty, value);
    }

    public readonly static DependencyProperty IsPlayingProperty = DependencyProperty.Register(
        nameof(IsPlaying), typeof(bool), typeof(PlayPauseButton), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
}

I want to bind to that property from its style. I want to show different images which depend on the IsPlaying flag value.

<Style TargetType="c:PlayPauseButton">
    <Setter Property="IsPlaying" Value="False"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate>
                <Grid>
                    <Image Width="100" Height="100" Visibility="{TemplateBinding IsPlaying, Converter={c:InverseBoolToVisibilityConverter}}">
                        ...
                    </Image>
                    <Image Width="100" Height="100" Visibility="{TemplateBinding IsPlaying, Converter={c:BoolToVisibilityConverter}}">
                        ...
                    </Image>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

I use the control like this:

<c:PlayPauseButton Width="200" Height="100" IsPlaying="{Binding Player.IsPlaying}"/>

But I have got a problem with the style. I can't bind to the IsPlaying property. You can see below error message:

"Failed to create 'DependencyProperty' based on text 'IsPlaying.': line number '10' and line position '75'."

CodePudding user response:

You have to specify the TargetType of the ControlTemplate, otherwise the property cannot be resolved in the TemplateBinding.

ControlTemplate TargetType="c:PlayPauseButton">

An alternative is to use a relative source binding to the templated parent.

<ControlTemplate>
   <Grid>
      <Image Width="100" Height="100" Visibility="{Binding IsPlaying, RelativeSource={RelativeSource TemplatedParent}, Converter={c:InverseBoolToVisibilityConverter}}">
          <!-- ... -->
      </Image>
      <Image Width="100" Height="100" Visibility="{Binding IsPlaying, RelativeSource={RelativeSource TemplatedParent}, Converter={c:BoolToVisibilityConverter}}">
          <!-- ... -->
      </Image>
   </Grid>
</ControlTemplate>
  • Related