You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF动态生成Grid触发静态Popup无法显示问题求助

WPF动态Grid触发静态Popup不显示问题

问题现象

在WPF应用中,动态生成的Grid行被点击时,静态定义在XAML中的Popup(实际是Grid)无法显示。设置Visibility=Visible后,日志显示IsVisible=false、ActualWidth/Height=0、IsLoaded=false;但通过XAML声明的静态控件调用相同的OpenPopUp方法时,Popup能正常显示。

已尝试的操作:验证可视化树、Dispatcher延迟执行、调用UpdateLayout()、更换触发事件、确认容器状态,均无效。

相关代码

动态生成Grid的方法

public Grid BasicGridTabel(DecodedAnswer answer, int count)
{
    Grid mainGrid = new Grid
    {
        Uid = answer.SekundarnaAdresa.ToString() + "/" + count,
        Cursor = Cursors.Hand,
    };
    mainGrid.MouseEnter += TableMouseHoverEnter_Grid;
    mainGrid.MouseLeave += TableMouseHoverLeave_Grid;
    mainGrid.PreviewMouseLeftButtonUp += (s, e) =>
    {
        e.Handled = true;
        Dispatcher.InvokeAsync(() => OpenPopUp(s, e), DispatcherPriority.Background);
    };

    if (count % 2 == 0)
    {
        mainGrid.Background = SheredColors.SelectedColor;
    }
    else
    {
        mainGrid.Background= SheredColors.SelectedTrueColor;
    }

    ScrollViewer scrollViewer = new ScrollViewer
    {
        HorizontalScrollBarVisibility = ScrollBarVisibility.Hidden,
        VerticalScrollBarVisibility = ScrollBarVisibility.Disabled,
    };

    StackPanel stackPanel = new StackPanel
    {
        Orientation = Orientation.Horizontal,
    };
    if (count > 0) 
        stackPanel.Children.Add(createNOTablePart(count)); //poradie

    List<recordToSend> records = new List<recordToSend>();
    records.Add(new() { Meaning = "Primárna Adresa", Hodnota = answer.PrimarnaAdresa.ToString(), DIF = answer.RawData });
    records.Add(new() { Meaning = "Sekundárna Adresa", Hodnota = answer.SekundarnaAdresa.ToString() });
    records.Add(new() { Meaning = "Výrobca", Hodnota = answer.Manufacturer.ToString() });
    records.Add(new() { Meaning = "Generácia", Hodnota=answer.Generation.ToString() });
    records.Add(new() { Meaning = "Médium", Hodnota = answer.Medium });
    records.Add(new() { Meaning = "Status Code", Hodnota = answer.StatusCode.ToString() });
    records.Add(new() { Meaning = "Počet Odpovedí", Hodnota = answer.NoOfRespons.ToString() });

    //hodnoty vyčítane z hlavičky
    foreach (var record in records)
    {
        Grid grid = createTablePart(record);
        stackPanel.Children.Add(grid);
    }

    //hodnoty vičítane z dat
    foreach (MbusDataRecord record in answer.DataRecords)
    {
        Grid grid = createTablePart(record);
        stackPanel.Children.Add(grid);
    }
    scrollViewer.Content = stackPanel;
    mainGrid.Children.Add(scrollViewer);

    return mainGrid;
}

放置动态Grid的容器XAML

<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Background="#333" Margin="0,0,0,8">
<StackPanel x:Name="StackPanleTable"
            Orientation="Vertical" VerticalAlignment="Top">
    <Grid>
        <ScrollViewer HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Disabled">
            <StackPanel Orientation="Horizontal">
                <Grid Width="auto">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="25"/>
                        <RowDefinition Height="30"/>
                    </Grid.RowDefinitions>
                    <Label Content="Test" Foreground="WhiteSmoke" Margin="5,0"/>
                    <Label Content="250" Foreground="WhiteSmoke"  Grid.Row="1" Margin="5,0" HorizontalAlignment="Center"/>
                    <Rectangle Stroke="WhiteSmoke" StrokeThickness="1" Grid.RowSpan="2"/>
                </Grid>

                <Grid Width="auto">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="25"/>
                        <RowDefinition Height="30"/>
                    </Grid.RowDefinitions>
                    <Label Content="Test" Foreground="WhiteSmoke" Margin="5,0"/>
                    <Label Content="00567894" Foreground="WhiteSmoke"  Grid.Row="1" Margin="5,0" HorizontalAlignment="Center"/>
                    <Rectangle Stroke="WhiteSmoke" StrokeThickness="1" Grid.RowSpan="2"/>
                </Grid>
            </StackPanel>
        </ScrollViewer>
    </Grid>
</StackPanel>
</ScrollViewer>

Popup的XAML定义

<Page x:Class="M_Bus.page_BasicMbus"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
  xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
  xmlns:local="clr-namespace:M_Bus"
  mc:Ignorable="d" 
  d:DesignHeight="909" d:DesignWidth="1200"
  Title="page_BasicMbus">
<Grid>
    <Grid x:Name="MAinGRID">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="5*"/>
        <ColumnDefinition Width="20*"/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="5*"/>
        <RowDefinition Height="15*"/>
        <RowDefinition Height="5*"/>
    </Grid.RowDefinitions>
    
    <Grid x:Name="MainPopUp"
          Grid.RowSpan="3" Grid.ColumnSpan="2"
          Panel.ZIndex="999" Visibility="Visible" IsVisibleChanged="MainPopUp_IsVisibleChanged"
          Background="#80000000"
          HorizontalAlignment="Stretch"
          VerticalAlignment="Stretch"
          Loaded="MainPopUp_Loaded"
          Unloaded="MainPopUp_Unloaded"
          MinHeight="100" MinWidth="100" 
          >
        <Rectangle x:Name="PopUpBackGroundFill" Fill="Black" Panel.ZIndex="1" Opacity="0.3"
                   Cursor="Hand"
                   MouseLeftButtonUp="HideMainPopUp"/>
        <Grid HorizontalAlignment="Center" VerticalAlignment="Center"
              Panel.ZIndex="2">
            <Rectangle Fill="Gray" RadiusX="10" RadiusY="10"
                       Stroke="Black" StrokeThickness="1" />
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="auto"/>
                    <RowDefinition Height="auto"/>
                    <RowDefinition Height="auto"/>
                </Grid.RowDefinitions>
                <Label Content="Nastavenia:" Foreground="WhiteSmoke"
                       FontSize="20" FontWeight="Bold" Margin="10"
                       VerticalAlignment="Center" HorizontalAlignment="Center"/>
                <Grid Grid.Row="1">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="auto"/>
                        <RowDefinition Height="auto"/>
                        <RowDefinition Height="auto"/>
                        <RowDefinition Height="auto"/>
                    </Grid.RowDefinitions>
                    <Label Content="General info:" Foreground="WhiteSmoke" Margin="5,0"/>

                    <Grid Grid.Row="1" Margin="10,5">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="auto"/>
                            <ColumnDefinition Width="auto"/>
                            <ColumnDefinition Width="auto"/>
                            <ColumnDefinition Width="auto"/>
                            <ColumnDefinition Width="auto"/>
                            <ColumnDefinition Width="auto"/>
                        </Grid.ColumnDefinitions>

                        <StackPanel Orientation="Vertical" Margin="2">
                            <Label Content="Primárna Adresa" Foreground="WhiteSmoke"
                                   HorizontalAlignment="Center" VerticalAlignment="Center"/>
                            <Label x:Name="primarnaAdresa_popUp" Content="250" Foreground="WhiteSmoke" 
                                   HorizontalAlignment="Center" VerticalAlignment="Center"/>
                        </StackPanel>
                        <StackPanel Orientation="Vertical" Margin="2" Grid.Column="1">
                            <Label Content="Sekundárna Adresa" Foreground="WhiteSmoke"
                                   HorizontalAlignment="Center" VerticalAlignment="Center"/>
                            <Label x:Name="sekundarnaAdresa_popUp" Content="00567892" Foreground="WhiteSmoke" 
                                   HorizontalAlignment="Center" VerticalAlignment="Center"/>
                        </StackPanel>
                        <StackPanel Orientation="Vertical" Margin="2" Grid.Column="3">
                            <Label Content="Výrobca" Foreground="WhiteSmoke"
                                   HorizontalAlignment="Center" VerticalAlignment="Center"/>
                            <Label x:Name="vyrobca_popUp" Content="APA" Foreground="WhiteSmoke" 
                                   HorizontalAlignment="Center" VerticalAlignment="Center"/>
                        </StackPanel>
                        <StackPanel Orientation="Vertical" Margin="2" Grid.Column="4">
                            <Label Content="Médium" Foreground="WhiteSmoke"
                                   HorizontalAlignment="Center" VerticalAlignment="Center"/>
                            <Label x:Name="Medium_popUp" Content="Water" Foreground="WhiteSmoke" 
                                   HorizontalAlignment="Center" VerticalAlignment="Center"/>
                        </StackPanel>
                        <StackPanel Orientation="Vertical" Margin="2" Grid.Column="5">
                            <Label Content="Status Code" Foreground="WhiteSmoke"
                                   HorizontalAlignment="Center" VerticalAlignment="Center"/>
                            <Label x:Name="statusCode_popUp" Content="FC" Foreground="WhiteSmoke" 
                                   HorizontalAlignment="Center" VerticalAlignment="Center"/>
                        </StackPanel>

                    </Grid>
                    <Grid Grid.Row="2">
                        <StackPanel Orientation="Vertical">
                            <Label Content="Raw Data received:" Margin="5,0"/>
                            <TextBlock x:Name="RawData_PopUp" TextWrapping="Wrap"/>
                        </StackPanel>
                        
                    </Grid>

                    <Grid x:Name="DataTOChange_PopUp_MainGrid" Grid.Row="3">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*"/>
                            <ColumnDefinition Width="*"/>
                            <ColumnDefinition Width="*"/>
                        </Grid.ColumnDefinitions>

                        <Label Content="Test" Margin="20,0,0,0" Foreground="WhiteSmoke"/>
                        <TextBox Grid.Column="1" Margin="10,2" Text=""
                                 VerticalAlignment="Center" Padding="2"/>

                        <Grid Uid="Test"
                              Margin="2"
                              Height="30"
                              Cursor="Hand"
                              MouseLeftButtonUp="vycitajRozsah"
                              Grid.Column="2">
                            <Rectangle  Fill="#60AA50" 
                                        RadiusX="10" RadiusY="10" Margin="2"
                                        />
                            <StackPanel Orientation="Horizontal" Height="20"
                                        VerticalAlignment="Center" HorizontalAlignment="Center">
                                <Grid Width="13" Height="13" Margin="0,0,10,0">
                                    <Rectangle Fill="White">
                                        <Rectangle.OpacityMask>
                                            <ImageBrush ImageSource="/Pages_Xaml/pencil.png" />
                                        </Rectangle.OpacityMask>
                                    </Rectangle>
                                </Grid>
                                <TextBlock Text="Zapísať" Margin="0" Padding="0"
                                           FontSize="13" Foreground="WhiteSmoke"
                                           TextWrapping="Wrap" TextAlignment="Center"
                                           HorizontalAlignment="Center" VerticalAlignment="Center"
                                           IsHitTestVisible="False" />
                            </StackPanel>

                        </Grid>
                    </Grid>
                </Grid>
            </Grid>

        </Grid>

    </Grid>
</Grid>
</Page>

打开Popup的方法

public void OpenPopUp(object sender, MouseButtonEventArgs e)
{
    MainPopUp.Visibility = Visibility.Visible;
    Dispatcher.InvokeAsync(() =>
    {
        Dispatcher.InvokeAsync(() =>
        {
            // teraz sa nachádzame až po plnom render cykle
            MainPopUp.Visibility = Visibility.Visible;
            MainPopUp.Opacity = 1;
            MainPopUp.IsHitTestVisible = true;

            Debug.WriteLine($"[DELAYED] IsLoaded: {MainPopUp.IsLoaded}, IsVisible: {MainPopUp.IsVisible}, ActualSize: {MainPopUp.ActualWidth}x{MainPopUp.ActualHeight}");
        }, DispatcherPriority.ApplicationIdle);
    }, DispatcherPriority.Background);
}

关闭Popup的方法

private void HideMainPopUp(object sender, MouseButtonEventArgs e)
{
    MainPopUp.Visibility = Visibility.Collapsed;
}

问题分析与解决方案

核心原因

  1. 事件截断导致UI流程异常:动态Grid使用PreviewMouseLeftButtonUp事件并设置e.Handled = true,截断了事件冒泡,干扰了WPF的UI布局更新逻辑——Popup的渲染依赖完整的事件循环,被截断的事件可能中断了布局调度。
  2. Dispatcher调用时机混乱:多层嵌套的Dispatcher.InvokeAsync导致Popup显示逻辑的执行时机延迟,甚至错过UI渲染周期。

解决方案

  1. 修改事件绑定逻辑

    • 移除e.Handled = true,保留事件冒泡;
    • 替换PreviewMouseLeftButtonUp为MouseLeftButtonUp(冒泡事件,不会提前截断UI流程)。

    修改后的事件绑定代码:

    mainGrid.MouseLeftButtonUp += (s, e) =>
    {
        Dispatcher.Invoke(() => OpenPopUp(s, e), DispatcherPriority.Normal);
    };
    
  2. 简化Popup显示逻辑
    去掉多层嵌套的Dispatcher.InvokeAsync,直接同步执行Popup显示逻辑,并强制更新布局:

    public void OpenPopUp(object sender, MouseButtonEventArgs e)
    {
        // 先填充Popup数据(需根据实际逻辑关联数据源)
        var clickedGrid = sender as Grid;
        // 示例:从Uid或关联的Tag获取DecodedAnswer实例
        var answer = GetAnswerFromGrid(clickedGrid);
        primarnaAdresa_popUp.Content = answer.PrimarnaAdresa.ToString();
        sekundarnaAdresa_popUp.Content = answer.SekundarnaAdresa.ToString();
        vyrobca_popUp.Content = answer.Manufacturer.ToString();
        Medium_popUp.Content = answer.Medium;
        statusCode_popUp.Content = answer.StatusCode.ToString();
        RawData_PopUp.Text = answer.RawData;
    
        MainPopUp.Visibility = Visibility.Visible;
        MainPopUp.UpdateLayout(); // 强制触发布局更新
        
        Debug.WriteLine($"IsLoaded: {MainPopUp.IsLoaded}, IsVisible: {MainPopUp.IsVisible}, ActualSize: {MainPopUp.ActualWidth}x{MainPopUp.ActualHeight}");
    }
    
  3. 修正Popup初始状态
    在XAML中将MainPopUp的初始Visibility设置为Collapsed,避免初始加载时的布局冲突:

    <Grid x:Name="MainPopUp"
          ...
          Visibility="Collapsed"
          ...>
    
  4. 验证可视化树关联
    在Page构造函数中添加日志,确认MainPopUp属于当前可视化树:

    public page_BasicMbus()
    {
        InitializeComponent();
        Debug.WriteLine($"MainPopUp Parent: {MainPopUp.Parent}, IsLoaded: {MainPopUp.IsLoaded}");
    }
    

补充说明

核心流程:读取Mbus串口设备响应 → 解析 → 创建BasicGridTabel → 鼠标左键抬起时获取Grid信息 → 填充Popup控件 → 打开Popup。修改后,动态Grid触发的Popup应能正常渲染显示。

内容的提问来源于stack exchange,提问作者Ryphath

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 00:18:14