WPF弹出窗口即使设置了StaysOpen="false"仍然无法关闭

3

我正在尝试实现以下内容:

  1. 用户在数据表格中打开上下文菜单。
  2. 用户选择上下文菜单项后,会弹出一个窗口并显示一些信息。
  3. 当用户在应用程序的其他位置(而不是在弹出窗口中)点击时,弹出窗口将关闭。

一切都很好,直到我来到关闭弹出窗口的部分。

从其他地方搜索后我知道我需要将Staysopen属性设置为false(已经这样做了),我还读到最好的方法是将IsOpen值绑定到视图模型中的属性,并将其绑定为双向绑定(也已完成)。

另外,我发现如果我添加一个文本框并单击框内,当我单击弹出窗口外部时,它会如预期那样关闭。

另一件我尝试过但没有成功的事情是通过编程方式设置文本框的键盘焦点,以获得所需的“自动关闭”功能。

以下是代码:

XAML -

<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会设置ViewModel上的属性。

 private void CurrentPredicitions_OnClick(object sender, RadRoutedEventArgs e)
        {

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

        }

视图模型属性
public bool? DisplaySummaryPopup
        {
            get
            {
                return this.displaySummaryPopup;
            }

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

如果您需要更多细节,请告诉我。

5个回答

3

这里有一个可工作的示例:

MainWindow 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 :

 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));
        }
    }

我认为你的INotifyPropertyChanged实现是引起问题的原因。我亲自尝试了代码,现在它已经可以工作。


2
尝试解决这个问题后,我发现问题与上下文菜单有关。我知道这是因为按照上面的答案,我不是通过上下文菜单启动弹出窗口,而是通过测试按钮启动它,所有操作都符合预期。
我仍然不知道这个问题的确切原因,但我认为这与上下文菜单本身是弹出窗口子类有关,焦点没有正确地设置在新弹出窗口上,因此它从未检测到弹出窗口丢失并关闭。
为了解决我的问题,我添加了一个关闭按钮到弹出窗口,每当承载弹出窗口的控件中的活动选项卡更改时,它会触发一个事件,弹出窗口接收并关闭。

2

我曾经遇到过同样的问题。原因是切换按钮的ClickMode属性被设置为“Press”。将其改回“Release”即可解决问题 :)


你真是救星,我在那上面花了很多时间。也帮助了我。 - Vadim Iarovikov

2
对我来说,解决方案是在弹出窗口代码后台的构造函数中添加这行代码:
LostFocus += delegate { this.IsOpen = false; };

许多小时的努力,当只需要这样一个简短的语句 :)

1

我曾多次遇到同样的问题。每次出现这种情况都是由于弹出窗口从列表视图或数据网格元素引发的事件(例如selectedItemChanged事件或items mouseUp事件)将其“isOpen”属性更改为true时。虽然我不知道原因,但通过以下代码从另一个任务中打开弹出窗口解决了这个问题:

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

Dispatcher被用于避免在非主线程上更改任何GUI对象属性时引发异常。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接