假设您有一个ToggleButton
用于打开Popup
,与ComboBox
等所有已知元素的行为相同。
...这是代码:
<ToggleButton x:Name="PART_OpenToggleButton"
Focusable="False"
IsChecked="False"
Template="{StaticResource MyToggleButton}">
<Grid>
<Popup x:Name="PART_PopupControl"
Style="{StaticResource MyPopupStyle}"
StaysOpen="False"
VerticalAlignment="Bottom"
IsOpen="False"
PlacementTarget="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ToggleButton, AncestorLevel=1}}" />
</Grid>
</ToggleButton>
然后在后面的代码中,IsOpen
使用Popup
,IsChecked
使用。ToggleButton
。
一切正常,但是当您打开Popup
并在边框外单击时问题就会到来。
Popup
将被关闭但ToggleButton
仍会被选中。
您无法在PopupOnClosed
的{{1}}处理程序中进行设置,因为当您点击ToggleButton.IsChecked = false
关闭ToggleButton
时,Popup
会自行关闭,设置Popup
,但是在您点击ToggleButton.IsChecked = false
的时间点,再次尝试打开 ToggleButton
。所以你无法关闭它。
1st ToggleButtonClick:
Popup
2nd ToggleButtonClick:
-> ToggleButton IsChecked = true
因此,如果在弹出窗口打开时单击切换按钮,它会闪烁但保持打开状态。
请问您如何解决这个问题?
编辑:
在MyWindow.XAML中尝试此操作并添加依赖项属性IsDropDownOpen 在后面的代码中,请:
-> ToggleButton IsChecked = false
-> ToggleButton IsChecked = true
答案 0 :(得分:3)
我在这篇文章中找到了解决方案:https://stackoverflow.com/a/5821819/651161
使用以下类将允许在按下togglebutton之前处理单击。弹出窗口因点击而关闭,但随后处理了点击,因此它不会触发ToggleButton点击。
public class MyPopup : Popup {
protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e) {
bool isOpen = this.IsOpen;
base.OnPreviewMouseLeftButtonDown(e);
if (isOpen && !this.IsOpen)
e.Handled = true;
}
}
答案 1 :(得分:2)
好的,这里有一些适用于我的代码(这些代码是从工作代码中复制粘贴的,其中删除了一些不感兴趣的部分):
以下是类似ComboBox的UserControl的内容:
<ToggleButton x:Name="Button" Height="19">
<Grid>
<Label Name="DisplayList" Content="Whatever" />
<Popup Name="SelectionPopup" MinHeight="100" MinWidth="200"
StaysOpen="False" IsOpen="{Binding IsChecked, ElementName=Button}">
</Popup>
</Grid>
</ToggleButton>
从自定义模板到实际的ComboBox:
<ToggleButton
Name="ToggleButton"
Template="{StaticResource ComboBoxToggleButton}"
Grid.Column="2"
Focusable="false"
IsChecked="{Binding Path=IsDropDownOpen,Mode=TwoWay,RelativeSource={RelativeSource TemplatedParent}}"
ClickMode="Press">
</ToggleButton>
<Popup
Name="Popup"
Placement="Bottom"
IsOpen="{TemplateBinding IsDropDownOpen}"
AllowsTransparency="True"
Focusable="False"
PopupAnimation="Slide">
答案 2 :(得分:1)
您可以将Popups StaysOpen
属性绑定到Buttons IsMouseOver
属性。这样,只要您点击弹出窗口(IsMouseOver = false = StaysOpen
)之外的内容,弹出窗口就会关闭,当点击ToggleButton
(IsMouseOver = true = StaysOpen
)时它会关闭弹出窗口。
这样,即使是弹出窗口外的点击也会被处理。
<ToggleButton x:Name="Toggle" />
<Popup x:Name="Popup" IsOpen="{Binding ElementName=Toggle, Path=IsChecked, Mode=TwoWay}"
StaysOpen="{Binding ElementName=Toggle, Path=IsMouseOver}" />
答案 3 :(得分:1)
第二个问题是 - 通过点击自动关闭 - 每次在弹出窗口外单击时都会发生,并且可以触发其他事件。即使你点击&#34;打开按钮&#34;关闭问题是 - 你不知道在popup.isOpen之前设置了哪个值 - 因为对于打开按钮的click事件处理程序,它总是为false。
我没有使用toggleButton来节省内存,但我认为关键问题是一样的。单击它时,toggleButton已经为假。
我的示例弹出窗口定义如下:
<Popup Placement="Bottom" PopupAnimation="Slide" Name="PART_Popup" VerticalOffset="3" AllowsTransparency="True" StaysOpen="False">
如果您点击展示位置目标 - 这是&#34;打开按钮&#34;弹出窗口关闭,同时处理了按钮的click事件,但是popup.IsOpen属性已经“错误”了。 - 所以它又被打开了。
我要解决的问题是订阅弹出窗口&#34;已关闭&#34;事件,节省了时间 - 阻止重新打开一秒钟。
DateTime? LastClose = new DateTime?();
private void Popup_Closed(object sender, EventArgs e)
{ LastClose = DateTime.Now; }
public bool AllowReopen
{
get {
if ((popup == null) || (popup.IsOpen)) return false;
//You cannot open, when the template isn't applied or it is already open
return !LastClose.HasValue || (DateTime.Now - LastClose.Value) > new TimeSpan(0,0,1) /*1s*/;
}
}
public void OpenPopup()
{
if (!AllowReopen) return;
popup.IsOpen = true;
}
答案 4 :(得分:0)
我会将两个人绑定到ViewModel中的同一个属性。您可以在Toolbox默认模板中找到很好的示例:
<ToggleButton x:Name="OverflowButton"
FocusVisualStyle="{x:Null}"
IsEnabled="{TemplateBinding HasOverflowItems}"
Style="{StaticResource ToolBarHorizontalOverflowButtonStyle}"
IsChecked="{Binding Path=IsOverflowOpen,Mode=TwoWay,RelativeSource={RelativeSource TemplatedParent}}"
ClickMode="Press"/>
<Popup x:Name="OverflowPopup"
AllowsTransparency="true"
Placement="Bottom"
IsOpen="{Binding Path=IsOverflowOpen,RelativeSource={RelativeSource TemplatedParent}}"
StaysOpen="false"
Focusable="false"
PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}">
<theme:SystemDropShadowChrome Name="Shdw" Color="Transparent">
<Border Background="{StaticResource ToolBarSubMenuBackground}"
BorderBrush="{StaticResource ToolBarMenuBorder}"
BorderThickness="1">
<ToolBarOverflowPanel x:Name="PART_ToolBarOverflowPanel"
Margin="2"
WrapWidth="200"
Focusable="true"
FocusVisualStyle="{x:Null}"
KeyboardNavigation.TabNavigation="Cycle"
KeyboardNavigation.DirectionalNavigation="Cycle"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
</theme:SystemDropShadowChrome>
</Popup>
希望这有帮助,
干杯,安瓦卡。
答案 5 :(得分:0)
要阻止通过单击其背景来关闭弹出窗口,请插入将填充它的内容。
在此示例中,单击未填充的空格将关闭弹出窗口:
<Popup x:Key="MyPop" Width="200" Height="200" StaysOpen="False">
<CheckBox Content="abc" />
</Popup>
在此示例中,单击未填充的空格将不会关闭弹出窗口:
<Popup x:Key="MyPop" Width="200" Height="200" StaysOpen="False">
<StackPanel Background="Red" Width="200" Height="200"> <!--EXTRA PANEL -->
<CheckBox Content="abc" />
</StackPanel>
</Popup>