如何正确地将Popup绑定到ToggleButton?

cra*_*mes 20 c# wpf xaml popup togglebutton

我试图从用户界面级别做一些看似相对简单和逻辑的东西,但我有一个非常烦人的错误.我有一个ToggleButton,我试图显示一个Popup按钮切换时,并隐藏Popup按钮切换时.在Popup当用户点击远离它也隐藏了.

一切都按照预期的方式使用以下XAML,除非在显示后单击切换按钮Popup,Popup消失一瞬间然后重新出现.

我怀疑这里发生了什么,点击远离Popup它是导致它关闭按钮然后立即切换按钮,因为鼠标点击它.我只是不知道如何修复它.

任何帮助表示赞赏.谢谢.

    <ToggleButton x:Name="TogglePopupButton" Content="My Popup Toggle Button" Width="100" />

    <Popup StaysOpen="False" IsOpen="{Binding IsChecked, ElementName=TogglePopupButton, Mode=TwoWay}">
        <Border Width="100" Height="200" Background="White" BorderThickness="1" BorderBrush="Black">
            <TextBlock>This is a test</TextBlock>
        </Border>                
    </Popup>
Run Code Online (Sandbox Code Playgroud)

sch*_*ola 35

Stephans的答案有一个缺点,即每当它失去焦点时关闭弹出窗口的所需行为也会消失.

我通过在弹出窗口打开时禁用切换按钮解决了这个问题.另一种方法是使用IsHitTestVisible属性而不是启用:

    <ToggleButton x:Name="TogglePopupButton" Content="My Popup Toggle Button" Width="100"  IsEnabled="{Binding ElementName=ToggledPopup, Path=IsOpen, Converter={StaticResource BoolToInvertedBoolConverter}}"/>
    <Popup x:Name="ToggledPopup" StaysOpen="False" IsOpen="{Binding IsChecked, ElementName=TogglePopupButton, Mode=TwoWay}">
        <Border Width="100" Height="200" Background="White" BorderThickness="1" BorderBrush="Black">
            <TextBlock>This is a test</TextBlock>
        </Border>                
    </Popup>
Run Code Online (Sandbox Code Playgroud)

转换器看起来像这样:

public class BoolToInvertedBoolConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value is bool)
        {
            bool boolValue = (bool)value;
            return !boolValue;
        }
        else
            return false;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException("ConvertBack() of BoolToInvertedBoolConverter is not implemented");
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 非常聪明.我使用了IsHitTestVisibile方法,因为出于其他原因我们需要IsEnabled. (4认同)
  • 这解决了这个问题,但解决方案显然取决于一些棘手的时机.当我用等效的视图模型绑定替换转换器时,它不再起作用.显然按下按钮设置IsOpen = false,重新启用ToggleButton,按钮向上触发ToggleButton.不知道为什么转换器版本有效.我担心,当新版本的框架发布或者以非平凡的方式使用此解决方案时,时机可能会爆炸. (3认同)
  • @RobertVažan 如果您向绑定添加延迟,则此解决方案的 ViewModel 版本似乎可以工作: `&lt;Popup IsOpen="{Binding IsPopupOpen, Delay=10}"&gt;` (2认同)

小智 21

没有IValueConverter的解决方案:

<Grid>
    <ToggleButton x:Name="TogglePopupButton" Content="My Popup Toggle Button" Width="100" >
        <ToggleButton.Style>
            <Style TargetType="{x:Type ToggleButton}">
                <Setter Property="IsHitTestVisible" Value="True"/>
                <Style.Triggers>
                    <DataTrigger Binding="{Binding ElementName=Popup, Path=IsOpen}" Value="True">
                        <Setter Property="IsHitTestVisible" Value="False"/>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </ToggleButton.Style>
    </ToggleButton>

    <Popup StaysOpen="false" IsOpen="{Binding IsChecked, ElementName=TogglePopupButton, Mode=TwoWay}"
               PlacementTarget="{Binding ElementName=TogglePopupButton}" PopupAnimation="Slide" 
           x:Name="Popup">
        <Border Width="100" Height="200" Background="White" BorderThickness="1" BorderBrush="Black">
            <TextBlock>This is a test</TextBlock>
        </Border>
    </Popup>
</Grid>
Run Code Online (Sandbox Code Playgroud)