У меня есть окно, которое переопределяет 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>





Кажется, я решил проблему, установив триггер в шаблоне элемента управления, который привязывается к 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. только код.
В xaml для вашего UserControl ... нет элемента с именем _this. Я думаю, что вы, возможно, забыли включить какой-то код.