要求
当用户选中其中一个切换按钮时,我希望它被选中并取消选中任何其他切换按钮。如果用户单击切换按钮,则其状态应从已选中更改为未选中或未选中更改为已选中。
问题
在IsChecked
事件的GotFocus
事件中设置ToggleButton
属性会导致Checked
事件被调用,然后神秘地取消选中ToggleButton
并导致要调用的Unchecked
事件。
代码
以下是我的实验室项目中的示例代码,用于演示此内容。
XAML:
<Grid>
<StackPanel x:Name="ToggleButtonContainer" Orientation="Horizontal" VerticalAlignment="Top">
<ToggleButton Content="Toggle 1" Margin="2" Padding="4" GotFocus="ToggleButton_GotFocus" Checked="ToggleButton_Checked" Unchecked="ToggleButton_Unchecked" />
<ToggleButton Content="Toggle 2" Margin="2" Padding="4" GotFocus="ToggleButton_GotFocus" Checked="ToggleButton_Checked" Unchecked="ToggleButton_Unchecked" />
<ToggleButton Content="Toggle 3" Margin="2" Padding="4" GotFocus="ToggleButton_GotFocus" Checked="ToggleButton_Checked" Unchecked="ToggleButton_Unchecked" />
<ToggleButton Content="Toggle 4" Margin="2" Padding="4" GotFocus="ToggleButton_GotFocus" Checked="ToggleButton_Checked" Unchecked="ToggleButton_Unchecked" />
<ToggleButton Content="Toggle 5" Margin="2" Padding="4" GotFocus="ToggleButton_GotFocus" Checked="ToggleButton_Checked" Unchecked="ToggleButton_Unchecked" />
</StackPanel>
</Grid>
CODE:
private void ToggleButton_Checked(object sender, RoutedEventArgs e)
{
System.Diagnostics.Debug.WriteLine("INFO: ToggleButton_Checked called by {0}", sender);
foreach (var toggleButton in ToggleButtonContainer.Children)
{
if (toggleButton != sender &&
(toggleButton as ToggleButton).IsChecked.HasValue &&
(toggleButton as ToggleButton).IsChecked.Value)
{
(toggleButton as ToggleButton).IsChecked = false;
}
}
}
private void ToggleButton_Unchecked(object sender, RoutedEventArgs e)
{
System.Diagnostics.Debug.WriteLine("INFO: ToggleButton_Unchecked called by {0}", sender);
}
private void ToggleButton_GotFocus(object sender, RoutedEventArgs e)
{
System.Diagnostics.Debug.WriteLine("INFO: ToggleButton_GotFocus called by {0}", sender);
(sender as ToggleButton).IsChecked = true;
}
环境信息
观察
我观察到,如果我在释放鼠标左键之前单击按钮并将其拖离,则我不会遇到此问题。调试并逐步执行Checked
事件时也会发生这种情况(因为调试器已经开始关注,ToggleButton
永远不会收到MouseLeftButtonUp
事件。
问题
答案 0 :(得分:1)
请告诉我这是否适合您。
XAML
<Grid>
<StackPanel x:Name="ToggleButtonContainer" Orientation="Horizontal" VerticalAlignment="Top">
<RadioButton Style="{StaticResource {x:Type ToggleButton}}" Content="Toggle 1" Margin="2" Padding="4" GotFocus="ToggleButton_GotFocus" Checked="ToggleButton_Checked" Unchecked="ToggleButton_Unchecked" />
<RadioButton Style="{StaticResource {x:Type ToggleButton}}" Content="Toggle 2" Margin="2" Padding="4" GotFocus="ToggleButton_GotFocus" Checked="ToggleButton_Checked" Unchecked="ToggleButton_Unchecked" />
<RadioButton Style="{StaticResource {x:Type ToggleButton}}" Content="Toggle 3" Margin="2" Padding="4" GotFocus="ToggleButton_GotFocus" Checked="ToggleButton_Checked" Unchecked="ToggleButton_Unchecked" />
<RadioButton Style="{StaticResource {x:Type ToggleButton}}" Content="Toggle 4" Margin="2" Padding="4" GotFocus="ToggleButton_GotFocus" Checked="ToggleButton_Checked" Unchecked="ToggleButton_Unchecked" />
<RadioButton Style="{StaticResource {x:Type ToggleButton}}" Content="Toggle 5" Margin="2" Padding="4" GotFocus="ToggleButton_GotFocus" Checked="ToggleButton_Checked" Unchecked="ToggleButton_Unchecked" />
</StackPanel>
</Grid>
CODE:
private void ToggleButton_Checked(object sender, RoutedEventArgs e)
{
System.Diagnostics.Debug.WriteLine("INFO: ToggleButton_Checked called by {0}", sender);
}
private void ToggleButton_Unchecked(object sender, RoutedEventArgs e)
{
System.Diagnostics.Debug.WriteLine("INFO: ToggleButton_Unchecked called by {0}", sender);
}
private void ToggleButton_GotFocus(object sender, RoutedEventArgs e)
{
System.Diagnostics.Debug.WriteLine("INFO: ToggleButton_GotFocus called by {0}", sender);
(sender as ToggleButton).IsChecked = true;
}
答案 1 :(得分:0)
使用GroupName属性在切换控件之间实现互斥。
<StackPanel>
<RadioButton GroupName="Os" Content="Windows XP" IsChecked="True"/>
<RadioButton GroupName="Os" Content="Windows Vista" />
<RadioButton GroupName="Os" Content="Windows 7" />
<RadioButton GroupName="Office" Content="Microsoft Office 2007" IsChecked="True"/>
<RadioButton GroupName="Office" Content="Microsoft Office 2003"/>
<RadioButton GroupName="Office" Content="Open Office"/>
</StackPanel>
答案 2 :(得分:0)
你可以通过一种风格来做到这一点。为了测试目的,如果切换按钮为5
,我已将checked
设置为focused
;如果获得checked
,则将控件设置为Foreground
,将Red
设置为<Style TargetType="ToggleButton" >
<Setter Property="IsChecked" Value="False" />
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Margin" Value="5" />
</Trigger>
<Trigger Property="IsFocused" Value="True">
<Setter Property="IsChecked" Value="True" />
<Setter Property="Foreground" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
。
{{1}}
答案 3 :(得分:0)
为什么按钮未选中?
该按钮变为未选中状态,因为IsChecked
事件中的GotFocus
属性已更改,但在OnClick
方法触发时会更改回来。
这是WPF中的错误还是我做错了什么?
看来当前的ToggleButton的设计意图是选择/取消选择它的唯一控件位于鼠标左键单击或空格键。
解决此问题的好处是什么? (如果有一个好的,干净的工作)
感谢this post以及与Janne Matikainen的对话,我能够提出以下解决方案:
public class MyToggleButton : ToggleButton
{
protected override void OnGotKeyboardFocus(KeyboardFocusChangedEventArgs e)
{
if (e.KeyboardDevice.IsKeyDown(Key.Tab))
{
IsChecked = true;
base.OnGotKeyboardFocus(e);
}
}
protected override void OnLostFocus(System.Windows.RoutedEventArgs e)
{
IsChecked = false;
base.OnLostFocus(e);
}
}
替换&lt; ToggleButton&gt;的所有实例与&lt; uc:MyToggleButton&gt;产生问题文本的“要求”部分中指定的行为。