【问题标题】:wpf popup doesn't close automatically when datagrid inside popup captures the mouse当弹出窗口内的数据网格捕获鼠标时,wpf弹出窗口不会自动关闭
【发布时间】:2011-04-27 16:57:16
【问题描述】:

我有一个带有StaysOpen=False 的弹出窗口,所以我想通过单击弹出窗口之外的任意位置来关闭它。在弹出窗口中,我有一个DataGrid。如果我打开弹出窗口,然后单击其他地方,弹出窗口将被关闭。但是,如果在单击弹出窗口外部之前单击DataGrid 中的列标题,则不会发生这种情况。测试 XAML:

<Window x:Class="Test.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" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="Black">
<Grid>
    <ToggleButton x:Name="btn" VerticalAlignment="Top">Open</ToggleButton>
    <Popup StaysOpen="False" IsOpen="{Binding IsChecked, ElementName=btn}" > 
        <DataGrid Width="150" Height="150">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Column" />
            </DataGrid.Columns>
        </DataGrid>
    </Popup>
</Grid>
</Window>

我认为这是因为列标题在单击时捕获了鼠标,而弹出窗口不再接收鼠标事件。我试图在LostMouseCapture 事件上添加一个处理程序,以便通过弹出窗口捕获鼠标,但它似乎并不那么容易。有什么想法吗?

【问题讨论】:

    标签: c# wpf popup grid mousecapture


    【解决方案1】:

    也许会有所帮助。 附行为:

    public class DataGridColumnHeaderReleaseMouseCaptureBehavior {
        public static DataGrid GetReleaseDGCHeaderBehavior(DependencyObject obj) {
            return (DataGrid)obj.GetValue(ReleaseDGCHeaderBehaviorProperty);
        }
    
        public static void SetReleaseDGCHeaderBehavior(DependencyObject obj, Boolean value) {
            obj.SetValue(ReleaseDGCHeaderBehaviorProperty, value);
        }
    
        public static readonly DependencyProperty ReleaseDGCHeaderBehaviorProperty =
            DependencyProperty.RegisterAttached("ReleaseDGCHeaderBehavior",
                typeof(DataGrid),
                typeof(DataGridColumnHeaderReleaseMouseCaptureBehavior),
                new UIPropertyMetadata(default(DataGrid), OnReleaseDGCHeaderBehaviorPropertyChanged));
    
        private static Popup _popup;
    
        private static void OnReleaseDGCHeaderBehaviorPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
            var oldGrid = (DataGrid)e.OldValue;
            if (oldGrid != null)
                oldGrid.MouseLeave -= OnMouseLeave;
            var refSender = d as Popup;
            _popup = refSender;
            if (refSender != null) {
                var refGrid = e.NewValue as DataGrid;
                if (refGrid != null) {
                    refGrid.MouseLeave += OnMouseLeave;
                }
            }
        }
        static void OnMouseLeave(object sender, MouseEventArgs args) {
            if (_popup != null)
                typeof(Popup).GetMethod("EstablishPopupCapture", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).Invoke(_popup, null);
        }
    }
    

    XAML:

    <Popup x:Name="popup"
    bhvrs:DataGridColumnHeaderReleaseMouseCaptureBehavior.ReleaseDGCHeaderBehavior="{Binding ElementName=dataGrid}">
      <DataGrid x:Name="dataGrid"/>
    </Popup>
    

    【讨论】:

      【解决方案2】:

      我认为您只是偶然发现了一个普通的老错误。我已经复制了这个,但找不到合理的方法让它工作。我认为您应该向 Microsoft 提交错误。它似乎是一个捕获鼠标的组件,而取消捕获它不会将捕获恢复到最初的捕获组件。

      【讨论】:

        【解决方案3】:

        我最近遇到了一个类似的问题,虽然不完全一样,而且是在 Silverlight 中。我通过在“行为不端”控件的所需事件处理程序中使用 GetTemplatedParent 函数搜索所需控件(在您的情况下是我猜的弹出窗口)来破解它,并以编程方式执行我想做的事情。

        这不是一个好的解决方案,也不能解决所有问题,但您可以尝试一下。一定要评论你做了什么,因为它可能会变成一团糟。

        【讨论】:

          【解决方案4】:

          我遇到了同样的问题,做了这样的事情:

           private void YourDataGrid_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
              {
                   YourDataGrid.CaptureMouse();
                   YourDataGrid.ReleaseMouseCapture();
              }
          

          但我正在寻找更好的东西......

          【讨论】:

            猜你喜欢
            • 2010-12-11
            • 1970-01-01
            • 2020-11-28
            • 1970-01-01
            • 1970-01-01
            • 2020-01-19
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多