Popup中ListBox的SelectChange事件关闭弹出窗体后主窗体点击无效BUG

2022-10-08,,,,

wpf的bug!
弹出框的 自定义控件里有popup, popup里面放一个listbox

 在listbox中的selectionchange事件触发关闭弹出框后,主窗体存在一定概率卡死(但点击标题又能用的bug)

 

步骤一: 新建个自定义wpf控件usercontrol

xaml代码:

<usercontrol x:class="wpfapplication1.usercontrol1"
             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:wpfapplication1"
             mc:ignorable="d" 
                 d:designheight="30" d:designwidth="200">
    <grid>
        <grid x:name="part_container">
            <dockpanel margin="0,0,1,0">
                <togglebutton x:name="part_toggbtn" dockpanel.dock="right" borderthickness="1" borderbrush="#959595" margin="-1,0,0,0" 
                          ischecked="{binding path=isdropdownopen,mode=twoway, relativesource={relativesource mode=findancestor, ancestortype=local:usercontrol1}}">
                    >
                </togglebutton>
                <textbox  x:name="txtautocomplete" />
            </dockpanel>
        </grid>
        <popup x:name="part_popup" opacity="0" width="{binding elementname=part_container,path=actualwidth}"
               isopen="{binding path=isdropdownopen,mode=oneway, relativesource={relativesource mode=findancestor, ancestortype=local:usercontrol1}}"
               popupanimation="slide" placement="bottom" staysopen="false" allowstransparency="true"
               placementtarget="{binding elementname=txtautocomplete}" verticaloffset="0" minheight="50" maxheight="300">
            <listbox x:name="listboxsuggestion" borderbrush="transparent" borderthickness="0">
                <listbox.itemtemplate>
                    <datatemplate>
                        <textblock text="{binding item1}"/>
                    </datatemplate>
                </listbox.itemtemplate>
            </listbox>
        </popup>
    </grid>
</usercontrol>

逻辑代码:

    public partial class usercontrol1 : usercontrol
    {
        public usercontrol1()
        {
            initializecomponent();
            list<tuple<string, string, string>> tupes = new list<tuple<string, string, string>>();
            enumerable.range(1, 10).select(p => p.tostring().padleft(3, '0')).tolist().foreach(p => tupes.add(new tuple<string, string, string>(p, p, p)));
            listboxsuggestion.itemssource = tupes;
            listboxsuggestion.selectionchanged += (o1, e1) =>
            {
                routedeventargs args = new routedeventargs(enterdownevent, o1); //选中项改变触发
                this.raiseevent(args);
            };
        }

        #region 回车触发事件
        //声明和注册路由事件
        public static readonly routedevent enterdownevent =
            eventmanager.registerroutedevent(
                "enterdown",
                routingstrategy.bubble,
                typeof(eventhandler<routedeventargs>),
                typeof(usercontrol1));
        //clr事件包装
        public event routedeventhandler enterdown
        {
            add { this.addhandler(enterdownevent, value); }
            remove { this.removehandler(enterdownevent, value); }
        }
        #endregion


        #region 是否打开下拉框
        public bool isdropdownopen
        {
            get { return (bool)getvalue(isdropdownopenproperty); }
            set
            {

                setvalue(isdropdownopenproperty, value);

            }
        }
        public static readonly dependencyproperty isdropdownopenproperty =
            dependencyproperty.register("isdropdownopen", typeof(bool), typeof(usercontrol1), new propertymetadata(false));
        #endregion
    }

步骤二: 新建个window窗体dialogwin

xaml代码

<window x:class="wpfapplication1.dialogwin"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:wpfapplication1"
        mc:ignorable="d"
        title="dialogwin" height="88.846" width="210">
    <grid>
        <local:usercontrol1 width="120" height="22" x:name="myselect"  />
    </grid>
</window>

cs代码

   public partial class dialogwin : window
    {
        public dialogwin()
        {
            initializecomponent();
            myselect.enterdown += (o1, e1) =>
            {
                this.close();
            };
        }
    }

  步骤三,在主窗体弹出dialogwin

xaml代码

<window x:class="wpfapplication1.mainwindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:wpfapplication1"
        mc:ignorable="d"
        title="mainwindow" height="350" width="525">
    <grid>
        <textbox x:name="textbox" horizontalalignment="left" height="23" margin="44,32,0,0" textwrapping="wrap" text="textbox" verticalalignment="top" width="120"/>
        <textbox  horizontalalignment="left" height="23" margin="198,32,0,0" textwrapping="wrap" text="textbox" verticalalignment="top" width="120"/>
        <textbox  horizontalalignment="left" height="23" margin="350,32,0,0" textwrapping="wrap" text="textbox" verticalalignment="top" width="120"/>
        <button x:name="button" content="button" horizontalalignment="left" verticalalignment="top" width="75" margin="44,82,0,0"/>
        <button x:name="button1" content="弹出对话框" horizontalalignment="left" verticalalignment="top" width="75" margin="156,82,0,0" click="button1_click"/>

    </grid>
</window>

  cs代码

/// <summary>
    /// mainwindow.xaml 的交互逻辑
    /// </summary>
    public partial class mainwindow : window
    {
        public mainwindow()
        {
            initializecomponent();
        }

        private void button1_click(object sender, routedeventargs e)
        {
            var s = new dialogwin();
            s.owner = this;
            s.windowstartuplocation = windowstartuplocation.centerowner;
            s.showdialog();
        }
    }

运行程序....

解决方案: 开启线程延迟关闭弹出体【最无语做法】

代码下载

《Popup中ListBox的SelectChange事件关闭弹出窗体后主窗体点击无效BUG.doc》

下载本文的Word格式文档,以方便收藏与打印。