WPF 컨트롤의 마우스 오버시의 백그라운드를 변경할려고 합니다.

아직도 wpf를 완전히 이해못해서 헤매고 있네요.
컨트롤에 마우스 커서를 올릴때 백그라운드를 파랗게 바꾸는 기본 동작을 제거하고
제가 지정한 색상으로 바꾸고 싶은데 이게 안됩니다.

컨트롤의 정의는 이렇습니다.

    <ToggleButton.Resources>
        <Style TargetType="{x:Type local:RoundToggleButton}">
            <Setter Property="Background" Value="Green"/>
            <Setter Property="MouseOverColor" Value="Red"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type local:RoundToggleButton}">
                        <Border x:Name="border" 
                                Background="{TemplateBinding Background}" >
                            <StackPanel>
                                
                                <ContentPresenter/>
                                <TextBlock Text="바인딩"
                                            Foreground="{TemplateBinding MouseOverColor}"/>
                            </StackPanel>
                        </Border>

                        <ControlTemplate.Triggers>
                           <Trigger Property="IsMouseOver" Value="True">
                               <Setter Property="Background" Value="{Binding MouseOverColor, RelativeSource={RelativeSource AncestorType=local:RoundToggleButton}}"/>
                           </Trigger>                            
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </ToggleButton.Resources>
</ToggleButton>

코드 비하인드 부분입니다.

public partial class RoundToggleButton : ToggleButton
{
    public static DependencyProperty MouseOverColorProperty;

    public Brush MouseOverColor
    {
        get => (Brush)GetValue(MouseOverColorProperty);
        set => SetValue(MouseOverColorProperty, value);
    }

    static RoundToggleButton()
    {
        MouseOverColorProperty = DependencyProperty.Register(
            nameof(MouseOverColor),
            typeof(Brush), 
            typeof(RoundToggleButton), 
            new FrameworkPropertyMetadata() 
            {
                AffectsRender= true, 
                Inherits= true,
                BindsTwoWayByDefault = true,
            });
    }

    public RoundToggleButton()
    {
        InitializeComponent();
    }
}

MouseOverColor가 제가 사용하고자 하는 브러쉬인데
Setter에서 MouseOverColor를 설정해도 TextBlock의 Foreground만 제대로 바뀌고
Trigger의 Setter로는 Red로 설정한 MouseOverColor가 아닌 기본값이 들어갑니다.
{Binding MouseOverColor}도 안되고요.

<Trigger Property="IsMouseOver" Value="True">
      <Setter Property="Background" Value="SeaGreen"/>
</Trigger>

이렇게 Brushes 값을 직접 입력해야 원하던 동작이 되는데
이러면 외부에서 바꾸지 못하니 제 문제가 해결되지가 않습니다.

Setter를 어떻게 정의해야 이 문제를 해결 할 수 있을까요?


자체 해결했습니다!
바인딩 설정 문제였더군요.

2개의 좋아요

@흡흡허 저도 WPF 개발하면서 많이 겪었던 고민이었는데요 :smile:

보여주신 소스코드에서 조금만 수정하시면 됩니다.

<JamesToggleButton MouseOverBackColor="#191919"/>

<Style Target="{x:Type JamesToggleButton}">
    <Setter Property="Background" Value="#DDDDDD"/>
    <Setter Property="Background" Value="#CCCCCC"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate Target="{x:Type JamesToggleButton}">
                <Border x:name="border" Background="{TemplateBinding Background">
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="true">
                        <Setter TargetName="border" Property="Background" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=MouseOverBackColor}"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

기본 Background는 기존처럼 TemplateBinding으로 하되, Trigger를 통한 IsMouseOver 변경 시점에서는 RelativeSource 바인딩을 통해 새롭게 만드신 DependencyProperty Brush를 변경해 주시면 됩니다.

여기서 TargetName이 필요한 이유는 Background 값을 변경하는 것이 아닌 값 자체를 새로운 DependencyProperty로 대체해주어야 하기 때문인데요. TargetName을 지정하지 않고도 되면 좋을탠데 TargetName을 지정하지 않으면 동작을 하지 않습니다.

아마 더 좋은 방식이 있을지도 모르겠습니다. :smile:

이렇게 한번 해보시길 바랍니다!
저도 매우 자주 쓰는 구조이기도 합니다.

2개의 좋아요

아 TargetName을 설정해서 바인딩하는 것도 있었네요
분명 배운 것인데 까먹고 있었다가 답변 보고서야 아!! 하고 기억이 났습니다…

해당 코드도 잘 동작되는걸 확인했습니다.
필요한 이유까지 적어주신 덕에 왜 이렇게 하는건지 간단히 알 수 있었네요.
답변 감사합니다!

2개의 좋아요