WPF - 将IsMouseOver绑定到Visibility

3
我有一个窗口,覆盖了一个RadioButton的ControlTemplate以在其内部显示自定义控件。在自定义控件中,我将一个按钮的可见性与IsMouseOver绑定,当鼠标悬停在控件上时,它能够正确地显示按钮。但是,当我单击RadioButton时,按钮消失了。经过调试和阅读资料,似乎RadioButton在单击时会捕获鼠标,这会使UserControl的IsMouseOver变为false。
我尝试将Button的可见性绑定到FindAncestor {x:Type RadioButton},它可以工作,但我认为让UserControl依赖于包含它的对象有点脆弱。下面是窗口和用户控件的代码。有什么建议吗?
<Window x:Name="window" x:Class="WPFTest.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:WPFTest="clr-namespace:WPFTest"
    Title="Window1" Height="300" Width="300">
    <Window.Resources>
        <Style TargetType="{x:Type RadioButton}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type RadioButton}">
                        <WPFTest:TestUC />
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>
    <Border BorderBrush="Black" BorderThickness="2">
        <StackPanel>
            <RadioButton x:Name="OptionButton" Height="100" />
            <TextBlock Text="{Binding ElementName=OptionButton, Path=IsMouseOver}" />
        </StackPanel>
    </Border>
</Window>

<UserControl x:Name="_this" x:Class="WPFTest.TestUC"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Height="300" Width="300">
    <UserControl.Resources>
        <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
    </UserControl.Resources>
    <StackPanel>
        <TextBlock Text="SomeText" />
        <TextBlock Text="{Binding ElementName=_this, Path=IsMouseOver}" />
        <Button x:Name="_cancelTextBlock" Content="Cancel" Visibility="{Binding ElementName=_this, Path=IsMouseOver, Converter={StaticResource BooleanToVisibilityConverter}}" />
    </StackPanel>
</UserControl>

在您的UserControl的xaml中...没有名为'_this'的元素。我认为您可能忘记了一些需要包含的代码。 - cplotts
3个回答

1

我似乎通过在控件模板中设置触发器来解决了问题,该触发器绑定到 RadioButton 的 IsMouseOver,并在 UserControl 上设置自定义 DependencyProperty。

类似这样:

<ControlTemplate TargetType="{x:Type RadioButton}">
    <WPFTest:TestUC x:Name="UC" />
    <ControlTemplate.Triggers>
        <Trigger Property="IsMouseOver" Value="True">
            <Setter Property="ShowCancel" Value="True" TargetName="UC"/>
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

我仍然困惑于为什么鼠标捕获会在 RadioButton 的 UserControl 子级上伪造 IsMouseOver。有人能解释一下吗?


1

在 RadioButton 处理事件后,它只是被标记为已处理,但实际上它仍然会冒泡。因此,您只需要指定您想要处理已处理的事件。

为此,您需要查看 handledEventsToo

不幸的是,我认为它不能在 XAML 中设置,只能在代码中设置。


0

非常有趣的问题。我自己也想更多地了解为什么当其可视化中的TextBlock被按下时,UserControl IsMouseOver会变为false。

然而,这里有另一种解决方法...也许你会更喜欢这种方法。

不要使用RadioButton(因为您正在重新模板化它),为什么不直接使用Control? (我认为IsMouseOver之所以会被更改为false是因为它是一个派生自Button的控件。)

以下是窗口的XAML代码...

<Window
    x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfApplication1"
    Title="Window1"
    Width="300"
    Height="300"
>
    <Window.Resources>
        <Style TargetType="{x:Type Control}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Control}">
                        <local:UserControl1/>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>

    <Border BorderBrush="Black" BorderThickness="2">
        <StackPanel>
            <Control x:Name="OptionButton" Height="100"/>
            <TextBlock Text="{Binding ElementName=OptionButton, Path=IsMouseOver}"/>
        </StackPanel>
    </Border>
</Window>

编辑:

我只是想要补充一下...如果你对上面的方法没有异议的话...那么,正确的做法可能就是直接在窗口的可视树中使用UserControl,而不是重新模板化一个控件。所以...像这样:

<Window
    x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfApplication1"
    Title="Window1"
    Width="300"
    Height="300"
>
    <Border BorderBrush="Black" BorderThickness="2">
        <StackPanel>
            <local:UserControl1 x:Name="OptionButton" Height="100"/>
            <TextBlock Text="{Binding ElementName=OptionButton, Path=IsMouseOver}"/>
        </StackPanel>
    </Border>
</Window>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接