WPF - привязка IsMouseOver к видимости - PullRequest
3 голосов
/ 03 ноября 2008

У меня есть окно, которое переопределяет RadioButton 'ControlTemplate, чтобы показать внутри него собственный элемент управления. Внутри пользовательского элемента управления у меня видимость кнопки привязана к IsMouseOver, которая работает правильно, показывая кнопку только тогда, когда мышь находится над элементом управления. Однако, когда я нажимаю на RadioButton, Button исчезает. После некоторой отладки и чтения кажется, что RadioButton захватывает мышь при щелчке, и это делает IsMouseOver для UserControl 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>

Ответы [ 3 ]

1 голос
/ 18 декабря 2008

После того, как событие обработано RadioButton, оно только устанавливает как обработанное, но в действительности оно все еще всплывает. Поэтому вам просто нужно указать, что вы хотите обрабатывать и обработанные события.

Для этого вам нужно взглянуть на handledEventsToo .

К сожалению, я не думаю, что это можно установить в xaml. только код.

1 голос
/ 03 ноября 2008

Кажется, я исправил проблему, установив триггер в шаблоне элемента управления, который привязывается к IsMouseOver в RadioButton и устанавливает пользовательский DependencyProperty в UserControl.

Что-то вроде:

<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>

Я все еще не понимаю, почему захват мыши фальсифицирует IsMouseOver на дочернем элементе UserControl объекта RadioButton. Может кто-нибудь пролить некоторый свет на это?

0 голосов
/ 03 ноября 2008

Очень интересная проблема. Я сам хотел бы узнать больше о том, почему UserControl IsMouseOver изменяется на false, когда TextBlock (ы) в его визуальных элементах нажимаются мышью.

Однако, есть еще один способ решить эту проблему ... возможно, вам больше понравится этот подход.

Вместо того, чтобы использовать 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>

EDIT:

Я просто хотел добавить ... что если вы согласны с вышеупомянутым подходом ... тогда, вероятно, правильнее всего будет просто использовать UserControl в визуальном дереве окна, а не использовать элемент Control. Итак ... вот так:

<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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...