呈现模板时WPF正在等待消息

呈现模板时WPF正在等待消息,wpf,treeview,datatemplate,Wpf,Treeview,Datatemplate,在我的遗留项目中,我有一个treeview和一个绑定在treeview叶子上的OnClick事件。基本上,每次选择叶时,我都会获得节点类型,并将模板应用到控件中,例如: gridDati.Template = Resources["tmplBit"] as ControlTemplate; “tmplBit”是一个具有多个列的数据模板。所有这些都很好,但有时当我有20列和30/40条记录时,应用所选模板需要时间(4/5秒)。 我想显示一条等待的消息,或类似的东西,但我找不到如何显示。我已经有一

在我的遗留项目中,我有一个treeview和一个绑定在treeview叶子上的OnClick事件。基本上,每次选择叶时,我都会获得节点类型,并将模板应用到控件中,例如:

gridDati.Template = Resources["tmplBit"] as ControlTemplate;
“tmplBit”是一个具有多个列的数据模板。所有这些都很好,但有时当我有20列和30/40条记录时,应用所选模板需要时间(4/5秒)。 我想显示一条等待的消息,或类似的东西,但我找不到如何显示。我已经有一个显示等待消息的窗口,我尝试将其用作:

    var aboutBox = new winWaitingMessage(Global.LM.T("@_3261_Inizio export"));
    aboutBox.Show();

    // Template?
    gridDati.Template = Resources["tmplBit"] as ControlTemplate;

    aboutBox.Close();

但是框会立即关闭,因此我找不到一个事件来告诉我何时应用和呈现模板。任何提示?

框架不提供此类事件,但您可以处理模板中某个元素的
加载事件,并在发生此事件时关闭窗口,例如:

gridDati.Template = Resources["tmplBit"] as ControlTemplate;
gridDati.ApplyTemplate();
FrameworkElement fe = gridDati.Template.FindName("YourElement", gridDati) as FrameworkElement;
if (fe == null)
{
    aboutBox.Close();  
}
else
{
    void Fe_Loaded(object sender, RoutedEventArgs e)
    {
        aboutBox.Close();
        fe.Loaded -= Fe_Loaded;
    }
    fe.Loaded += Fe_Loaded;
}
XAML:

<ControlTemplate x:Key="tmplBit">
    ...
    <Button x:Name="YourElement" ... />
您可以使用任务

[DllImport("user32.dll", CharSet = CharSet.Auto)]
        static extern IntPtr FindWindow(IntPtr hwnd, string title);
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        static extern int PostMessage(IntPtr hwnd, int msg, uint wParam, uint lParam);
        public const int WM_CLOSE = 0x10; 

        public const int WM_KEYDOWN = 0x0100;

        public const int WM_KEYUP = 0x0101;

        public const int VK_RETURN = 0x0D;


        private   void Button_Click(object sender, RoutedEventArgs e)
        {
            Task task1 = new Task(() => 
            {

                   gridDati.Template = Resources["tmplBit"] as ControlTemplate;

            });
            task1.Start();
            Task cwt = task1.ContinueWith(t=>
            {
                FindAndKillWindow("Warning");
            });
            MessageBox.Show("Waiting...", "Warning");        
        }

        private static void FindAndKillWindow(string title)
        {
            IntPtr ptr = FindWindow(IntPtr.Zero, title);
            if (ptr != IntPtr.Zero)
            {
                int ret = PostMessage(ptr, WM_CLOSE, 0, 0);

                ptr = FindWindow(IntPtr.Zero, title);
                if (ptr != IntPtr.Zero)
                {
                    PostMessage(ptr, WM_KEYDOWN, VK_RETURN, 0);
                    PostMessage(ptr, WM_KEYUP, VK_RETURN, 0);
                }
            }
        }

嗯,听起来很奇怪,你怎么能在if中声明一个方法?@Spaccaspecchi:它被称为一个局部函数,是在C#7.0中引入的:我明白了,但我仍然在使用.NET 4。5@Spaccaspecchi:您仍然可以使用C#7.0。或者干脆不使用局部函数,而是使用lambda表达式。请参见“我的编辑”以获取示例。@Spaccaspecchi:如果您的问题已经解决,请记住接受答案并投票表决。它不起作用,消息框在整个数据网格渲染之前被杀死。我仍在努力寻找一个事件,它让我有机会完全呈现我的控制权
[DllImport("user32.dll", CharSet = CharSet.Auto)]
        static extern IntPtr FindWindow(IntPtr hwnd, string title);
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        static extern int PostMessage(IntPtr hwnd, int msg, uint wParam, uint lParam);
        public const int WM_CLOSE = 0x10; 

        public const int WM_KEYDOWN = 0x0100;

        public const int WM_KEYUP = 0x0101;

        public const int VK_RETURN = 0x0D;


        private   void Button_Click(object sender, RoutedEventArgs e)
        {
            Task task1 = new Task(() => 
            {

                   gridDati.Template = Resources["tmplBit"] as ControlTemplate;

            });
            task1.Start();
            Task cwt = task1.ContinueWith(t=>
            {
                FindAndKillWindow("Warning");
            });
            MessageBox.Show("Waiting...", "Warning");        
        }

        private static void FindAndKillWindow(string title)
        {
            IntPtr ptr = FindWindow(IntPtr.Zero, title);
            if (ptr != IntPtr.Zero)
            {
                int ret = PostMessage(ptr, WM_CLOSE, 0, 0);

                ptr = FindWindow(IntPtr.Zero, title);
                if (ptr != IntPtr.Zero)
                {
                    PostMessage(ptr, WM_KEYDOWN, VK_RETURN, 0);
                    PostMessage(ptr, WM_KEYUP, VK_RETURN, 0);
                }
            }
        }