简体   繁体   English

即使使用 StaysOpen="false",WPF 弹出窗口也不会关闭

[英]WPF popup wont close even with StaysOpen="false"

I am trying to achieve the following:我正在努力实现以下目标:

  1. User brings up a context menu in a datagrid.用户在数据网格中调出上下文菜单。
  2. User selects a context menu item which then opens a popup and displays some information.用户选择一个上下文菜单项,然后打开一个弹出窗口并显示一些信息。
  3. when the user clicks anywhere else in the application, not in the popup, the popup closes.当用户单击应用程序中的任何其他位置时,而不是在弹出窗口中,弹出窗口将关闭。

Everything works fine until I come to closing the popup.一切正常,直到我关闭弹出窗口。

From searching elsewhere I am aware that I need Staysopen to be set to false ( which it is) I also read the best way is to bind the IsOpen value to a property in the view model and set its binding to 2 way ( also done )从其他地方搜索我知道我需要将 Staysopen 设置为 false (它是)我还阅读了最好的方法是将 IsOpen 值绑定到视图模型中的属性并将其绑定设置为 2 方式(也完成)

As a side note I have found that if I add a textbox and click inside the box, when I then click outside the popup it closes as desired.作为旁注,我发现如果我添加一个文本框并在框内单击,然后当我在弹出窗口外部单击时,它会根据需要关闭。

Another thing I unsuccessfully tried as a workaround was to programmatically set the keyboard focus on the text box to get the "autoclose" functionality I desired.我作为解决方法尝试的另一件事是,以编程方式将键盘焦点设置在文本框上以获得我想要的“自动关闭”功能。

Here is code:这是代码:

xaml - xml -

<Popup Name="PredictionsPopup" Height="200" Width="200" AllowsTransparency="false" StaysOpen="False" IsOpen="{Binding DisplaySummaryPopup, Mode=TwoWay}">
            <StackPanel Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}">
                <TextBlock Text="here is some stuff" />
                <TextBox Name="hiddenBox" Text="moo"/>
            </StackPanel>         
        </Popup>

Codebehind that sets the property on the viewmodel when the menu item is selected.选择菜单项时在视图模型上设置属性的代码隐藏。

 private void CurrentPredicitions_OnClick(object sender, RadRoutedEventArgs e)
        {

            PredictionsPopup.Placement = PlacementMode.MousePoint;
            ViewModel.DisplaySummaryPopup = true;

        }

Viewmodel property视图模型属性

public bool? DisplaySummaryPopup
        {
            get
            {
                return this.displaySummaryPopup;
            }

            set
            {
                this.displaySummaryPopup = value;
                RaisePropertyChanged(() => this.DisplaySummaryPopup);
            }
        }

Please let me know if you need anymore details.如果您需要更多详细信息,请告诉我。

Here you face an working example:在这里,您面临一个工作示例:

MainWindow XAML:主窗口 XAML:

<Window x:Class="WpfApplication2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Popup Name="PredictionsPopup" Height="200" Width="200" AllowsTransparency="false" StaysOpen="False" IsOpen="{Binding DisplaySummaryPopup, Mode=TwoWay}">
            <StackPanel Background="Red">
                <TextBlock Text="here is some stuff" />
                <TextBox Name="hiddenBox" Text="moo"/>
            </StackPanel>
        </Popup>
        <DataGrid AutoGenerateColumns="False"  Name="dataGrid1"  IsReadOnly="True" >
            <DataGrid.Columns>
                <DataGridTextColumn Header="Site"  Width="150" />
                <DataGridTextColumn Header="Subject"  Width="310" />
            </DataGrid.Columns>
            <DataGrid.ContextMenu>
                <ContextMenu>
                    <MenuItem Header="Click Me" Click="ButtonBase_OnClick">                     
                    </MenuItem>
                </ContextMenu>
            </DataGrid.ContextMenu>
        </DataGrid>


    </Grid>
</Window>

MainWindow cs :主窗口 cs :

 public MainWindow()
        {
            InitializeComponent();
            DataContext = new TestViewModel();
        }

        private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
        {
            PredictionsPopup.Placement = PlacementMode.MousePoint;
            PredictionsPopup.IsOpen = true;

        }

ViewModel:视图模型:

  public class TestViewModel : INotifyPropertyChanged
    {
        private bool _displaySumarry;
        public bool DisplaySummaryPopup
        {
            get { return _displaySumarry;  }
            set
            {
                _displaySumarry = value;
                OnPropertyChanged();
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            var handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }

I think that your implementation for INotifyPropertyChanged is the one which causes the problem.我认为您对 INotifyPropertyChanged 的​​实现是导致问题的原因。 I tried myself the code and is working now.我尝试了自己的代码,现在正在工作。

After trying to track this problem down I worked out that the issue is something to do with the context menu.在尝试跟踪此问题后,我发现问题与上下文菜单有关。 I know this because as per the answer above instead of launching my popup via a context menu I launched it from a test button and all worked as expected.我知道这一点,因为根据上面的答案,我没有通过上下文菜单启动我的弹出窗口,而是从测试按钮启动它,并且一切都按预期工作。

I still don't know the exact reason for this issue but I think its something to do with the fact that the context menu is itself a subclass of popup and the focus isn't being set correctly on the new popup, so it never detects popup loss and closes.我仍然不知道这个问题的确切原因,但我认为这与上下文菜单本身是弹出窗口的子类并且焦点没有正确设置在新弹出窗口上的事实有关,所以它永远不会检测到弹出窗口丢失并关闭。

To get round my problem I have added a close button to the popup, and then whenever the active tab in the control that hosts the popup changes it fires an event that the popup picks up and closes.为了解决我的问题,我在弹出窗口中添加了一个关闭按钮,然后每当托管弹出窗口的控件中的活动选项卡发生更改时,它都会触发一个事件,弹出窗口将被选中并关闭。

I faced same problem a few times.我几次遇到同样的问题。 Every time it was occuring, when a popup was changing its "isOpen" property to true from an event, which was raised from listview or datagrid element, like selectedItemChanged event, or items mouseUp event.每次发生时,当弹出窗口将其“isOpen”属性从一个事件更改为 true 时,该事件是从 listview 或 datagrid 元素引发的,如 selectedItemChanged 事件或 items mouseUp 事件。 I don't know reason, however resolved it by opening the popup from another task with code as below:我不知道原因,但是通过使用以下代码打开另一个任务的弹出窗口来解决它:

Task.Run(()=> Dispatcher.Invoke( () => myPopup.IsOpen = true));

Dispatcher is used to avoid an exception from changing any GUI object property from another than the main thread. Dispatcher 用于避免从除主线程之外的另一个更改任何 GUI 对象属性的异常。

Had the same problem.有同样的问题。 The reason was, that the toggle button's ClickMode property was set to "Press".原因是,切换按钮的 ClickMode 属性设置为“按下”。 Setting it back to "Release" solved it :).将其设置回“发布”解决了它:)。

For me, the solution was to add this line in the constructor of the popup's code-behind:对我来说,解决方案是在弹出窗口代码隐藏的构造函数中添加这一行:

LostFocus += delegate { this.IsOpen = false; };

Many hours were spent, when such a quickie line was all it took :)花了很多小时,当这样一条快速路线就完成了:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM