WPF ComboBox下拉部分出现位置错误

3

我在一个 XAML 窗口上放置了几个下拉列表框。当我展开它们中的任意一个时,下拉部分出现在屏幕左上角。

我使用的是 Visual Studio 2008 C# Express。我不记得在使用 Visual Studio 2008(试用版)时有这种现象,尽管我使用的是相同的框架 (3.5)。


5
请提供更多细节和/或代码。 - Natrium
6个回答

1
这似乎是WPF中的一个错误。在我的情况下,我试图在另一个窗口的Loaded事件中打开一个窗口。为了解决这个问题,我设置了一个计时器来触发,然后使用委托来打开窗口(不能在计时器事件中打开窗口,因为打开窗口的调用线程必须是STA)。
编辑 - 计时器不必要 - 没有看到上面的答案,只需将其排队到调度程序...
private delegate void DelegateOpenWindow();
private DelegateOpenWindow m_DelegateOpenWindow;
private Timer loginTimer = new Timer(200);

private void MainWindow1_Loaded(object sender, RoutedEventArgs e)
{
        // create delegate used for asynchronous call
        m_DelegateOpenWindow= new DelegateOpenWindow(this.OpenWindow);
        // start a timer to fire off the open window.
        loginTimer.Elapsed += loginTimer_Elapsed;
        loginTimer.Enabled = true;
}

void loginTimer_Elapsed(object sender, ElapsedEventArgs e)
{
        loginTimer.Enabled = false;
        this.Dispatcher.BeginInvoke(m_DelegateOpenWindow);

}

void OpenWindow()
{
        MyWindow w = new MyWindow();
        w.Owner = this;
        w.ShowDialog();
}

1

这似乎是一个bug。

解决方法:

使用Window.Show()代替,并使用自定义逻辑模拟ShowDialog()的行为。


0

昨天我开始观察到这个问题(以及其他奇怪的行为习惯),当我尝试从Window.Loaded事件处理程序中“微调”窗口大小、形状、颜色并调用登录对话框时。在每个MVVM模式应用程序的代码后台中,我一直都做得很好。昨天,我决定将其从每个应用程序的代码后台移动到一个合并的代码后台基类中,因为预处理已经在所有这些应用程序中变得普遍。当我这样做时,登录对话框中两个ComboBox中的下拉菜单突然出现在屏幕的左上角。我似乎通过使用以下技术来“解决”它(您的结果可能会有所不同):

    protected void WindowBaseLoadedHandler(object sender, RoutedEventArgs e)
    {
...non-essential lines of code removed...

        if (DataContext != null)
        {
            Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
            {
                /*----------------------------------------------------------------------
                 * Do we have a View Model? If so, perform standard VM Initialization...
                 *---------------------------------------------------------------------*/
                this.IsEnabled = false;

                LoginDlg loginDlg = new LoginDlg();
                loginDlg.ShowDialog();

                if (!loginDlg.Success)
                {
                    /*-----------------------------------
                     * Log on failed -- terminate app...
                     *----------------------------------*/
                    ...termination logic removed...
                }

                this.IsEnabled = true;
            }));
        }

WindowBaseLoadedHandler 是 Loaded 事件处理程序。LoginDlg 是一个 WPF 应用程序,其中包含两个 ComboBox 的对话框。

回顾一下:在我将代码合并到基类的 Loaded 事件处理程序中后,ComboBox 的下拉列表出现在屏幕的左上角。一旦我将逻辑封装到 Dispatcher.BeginInvoke 调用中,适当的 ComboBox 行为就会返回,并显示当前项目下方的列表。

我怀疑 WPF 需要应用程序从 Loaded 事件返回以完成布局系统的初始化。这并不能完全解释为什么之前可以工作,但我将把追寻“为什么”的愿望留到未来的某个雨天,并庆祝今天克服了最新的障碍。

无论如何,我希望有人能从中受益。


0

我正在使用最新的 .Net 4.5 和 WPF 框架,但仍然遇到这个问题。我注意到的一件事是,只有在附加了调试器时才会出现这个问题。当调试器未附加时,一切正常。


0

我在Visual Studio 2019上遇到了同样的问题。 使用window.Show()可以解决问题,但可能会破坏您的设计。 解决方法是异步打开窗口。

var yourDialog= new YourDialog();
yourDialog.Owner = this;
TaskCompletionSource<bool?> completion = new TaskCompletionSource<bool?>();
this.Dispatcher.BeginInvoke(new Action(() => 
completion.SetResult(yourDialog.ShowDialog())));
bool? result = await completion.Task;

你也可以通过创建扩展方法来实现更优雅的解决方案:

public static class AsyncWindowExtension
{
    public static Task<bool?> ShowDialogAsync(this Window self)
    {
        if (self == null) throw new ArgumentNullException("self");

        TaskCompletionSource<bool?> completion = new TaskCompletionSource<bool?>();
        self.Dispatcher.BeginInvoke(new Action(() => completion.SetResult(self.ShowDialog())));

        return completion.Task;
    }
}

你可以像这样使用它:

await dlgReview.ShowDialogAsync();

-1

这是WPF中的一个bug(恐怕不是唯一的一个)。当我在Loaded事件中打开另一个窗口时,就会出现这个问题,类似于:

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    Window selectionWindow = new SelectionWindow();
    bool? result = selectionWindow.ShowDialog();
    if (result == true)
        RecordChanged();
}

我已经找到了一个解决方法。


我猜解决方法是在单独的消息中打开窗口。也就是说,Loaded处理程序在Dispatcher上排队另一条消息,以打开Window - Kent Boogaart
告诉我们这是个bug,加一分;开玩笑说你有一个workabout,扣一分。 - Jake Berger

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