WPF - привязка IsMouseOver к видимости

У меня есть окно, которое переопределяет RadioButtonControlTemplate, чтобы показать внутри него настраиваемый элемент управления. Внутри настраиваемого элемента управления у меня есть видимость кнопки, привязанная к IsMouseOver, которая правильно работает, показывая кнопку только тогда, когда мышь находится над элементом управления. Однако, когда я нажимаю на RadioButton, Button исчезает. После некоторой отладки и чтения кажется, что RadioButton захватывает мышь при щелчке, и это делает IsMouseOver для UserControl ложным.

Я попытался привязать видимость 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>

В xaml для вашего UserControl ... нет элемента с именем _this. Я думаю, что вы, возможно, забыли включить какой-то код.

cplotts 03.11.2008 17:54
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
1
11 666
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Кажется, я решил проблему, установив триггер в шаблоне элемента управления, который привязывается к 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>

Однако я все еще не понимаю, почему Mouse Capture фальсифицирует IsMouseOver в дочернем элементе UserControl RadioButton. Может кто-нибудь пролить некоторый свет на это?

Очень интересная проблема. Я сам хотел бы узнать больше о том, почему 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 в визуальном дереве окна вместо повторного создания элемента 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>

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

Для этого вам нужно посмотреть handledEventsToo.

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

Другие вопросы по теме