ToolBarOverflow面板中的弹出窗口无法正常工作

时间:2015-11-26 09:18:27

标签: c# wpf popup toolbar

我的应用程序中有ToolBar导致问题。 我有" DropDown" ToolBar内的按钮(ToggleButton + Popup)如果这些DropDow位于ToolBar的可见部分,则它们可正常工作,如果它们位于ToolBarOverflowPanel,它们将无法正常工作ToolBarOverflowPanel

如果我在Popup中打开DropDown,则Popup似乎无法获得焦点。仍然有悬停效果(与可见工具栏中相同Mouse的行为相反,似乎消耗了所有Popup个事件),我仍然可以点击任何其他DropDown打开下一个{{1}而最初的一个保持打开状态。

Here you can see the wrong behaviour

以下代码是重现行为的完整工作示例。

<Window x:Class="ToolbarProblem.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Height="350"
    Width="525">
<StackPanel>
    <ToolBar ItemsSource="{Binding Items}">
        <ToolBar.ItemTemplate>
            <DataTemplate >
                <StackPanel VerticalAlignment="Center"
                            Orientation="Horizontal">
                    <ToggleButton Name="ToggleButton"
                                  ToolTip="ToolTip"
                                  IsChecked="{Binding ElementName=ContextActionPopup, Path=IsOpen, Mode=TwoWay}"
                                  ClickMode="Release">
                        <TextBlock Text="ICON"/>
                    </ToggleButton>
                    <Popup Name="ContextActionPopup"
                           StaysOpen="False">
                        <Border x:Name="Border" 
                                Background="White"
                                Padding="1"
                                Visibility="Visible">
                            <TextBlock Text="Content" />
                        </Border>
                    </Popup>
                </StackPanel>
            </DataTemplate>
        </ToolBar.ItemTemplate>
    </ToolBar>
</StackPanel>

namespace ToolbarProblem
{
    using System.Collections.Generic;

    public partial class MainWindow
    {
        public MainWindow()
        {
            this.InitializeComponent();
            this.DataContext = new MainWindowViewModel();
        }
    }

    public class MainWindowViewModel
    {
        public List<object> Items { get; } = new List<object>
        {
            new object(),
            new object(),
            new object(),
            new object(),
            new object(),
            new object(),
            new object(),
            new object(),
            new object(),
            new object(),
            new object(),
            new object(),
            new object(),
            new object(),
            new object(),
            new object(),
            new object(),
            new object(),
            new object(),
            new object()
        };
    }
}

我确实尝试了以下方法但没有取得任何成功:

  • 添加一些代码以致电Popup.Focus
  • ToggleButton.ClickMode更改为可能的所有内容
  • Popup.StaysOpen属性设置为true似乎确实有效,但确实如此 当然不适合我的目标

1 个答案:

答案 0 :(得分:1)

我担心你的XAML永远不会正常工作。您可以在Popup控制代码中找到原因。如果您将StaysOpen属性设置为false,则Popup在打开时会调用此私有方法(只需使用ILSpy进行检查):

private void EstablishPopupCapture()
{
    if (!this._cacheValid[1] && this._popupRoot.Value != null && !this.StaysOpen && Mouse.Captured == null)
    {
        Mouse.Capture(this._popupRoot.Value, CaptureMode.SubTree);
        this._cacheValid[1] = true;
    }
}

因此,如果没有其他控件捕获鼠标事件(即Mouse.Captured == null),您的弹出窗口将捕获它们

  

确定其中一个事件何时发生在Popup控件之外。

作为MSDN的评论。请注意,Capture方法和Captured属性是静态的,因此一次只能使用Mouse类捕获一个控件。

现在只需查看Toolbar默认样式:您会发现其Popup控件名为&#34; OverflowPopup&#34;,其StaysOpen属性设置为假的。

所以当你点击溢出的拇指时,&#34; OverflowPopup&#34>在EstablishPopupCapture打开时调用Mouse.Captured。在这种情况下,ToggleButton为null,因此它可以捕获鼠标事件。 过了一会儿,你点击了一个EstablishPopupCapture,它位于&#34; OverflowPopup&#34; (所以它会继续保持开放)。现在,您的弹出窗口 - 在打开时调用Mouse.Captured,但这次Mouse null。因此,无法使用StaysOpen类来监听鼠标事件。

我想您应该考虑更改XAML或采用不同的解决方案(例如,您可以为工具栏编写自己的模板,以便将OverflowPopup的<StackPanel Orientation="Horizontal"> <Button Content="I am button 1" Name="btn1" Height="20" /> <Button Content="I am button 2" Name="btn2" Height="20" /> <Popup StaysOpen="False" IsOpen="True" PlacementTarget="{Binding ElementName=btn1}"> <TextBlock Text="Popup1" Margin="6" Background="Red" /> </Popup> <Popup StaysOpen="False" IsOpen="True" PlacementTarget="{Binding ElementName=btn2}"> <TextBlock Text="Popup2" Margin="6" Background="Red" /> </Popup> </StackPanel> 属性设置为true。

这是一个简化的解释,但问题是不可能将两个或多个打开的弹出窗口设置为假的StaysOpen:它们根本无法按预期工作。试着运行这个XAML:

func createButton (items: [String], margin: Int) {
    let customSC = UISegmentedControl(items: items)
    let frame = UIScreen.mainScreen().bounds

    customSC.selectedSegmentIndex = 0
    customSC.frame = CGRectMake(56, CGFloat(50 + margin), 200, 30) // X, Y, width, height
    customSC.addTarget(self, action: "buttonPressed:", forControlEvents: .TouchUpInside)
    self.view.addSubview(customSC)
}

你会看到Popup2无法正常工作。