动态设置弹出窗口的位置/位置 [英] Dynamically set the Popup position/placement

查看:110
本文介绍了动态设置弹出窗口的位置/位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Popup控件默认为左对齐.它的左边缘与父对象的左边缘对齐.

我想做的是使控件右对齐,以便控件的右边缘与容器的右边缘对齐.

我希望它是动态的,因为我动态绑定了数据并且不知道弹出窗口的大小.

我尝试使用OpenedSizeChangedLoaded事件来获取Child的宽度并将其设置为HorizontalOffset,但是似乎存在计时问题.基本上,它在第一次加载控件时就可以正常运行,然后再加载(HorizontalOffset设置为0)就可以了.

这是一个错误吗?我做错了吗?

编辑,我可以正常使用.似乎存在计时问题.如果我挂起Opened事件并使用Dispatcher异步设置HorizontalOffset,则它会起作用:(

编辑2 我现在意识到自己在做一些愚蠢的事情.我希望ComboBoxPopup右对齐.我没有看到它在ArrangePopup私有方法调用中被重新初始化. 我尝试从ComboBox继承以覆盖放置函数,但是我必须做错了什么,因为尽管我覆盖了调用ArrangePopup

的方法,但它似乎仍然无法正常工作

干杯.

解决方案

我现在意识到,如果我不回答自己的问题,没有人能够将我的解决方法标记为答案.这是完整的代码.我将其实现为PRISM行为.

public static class PopupRightAlignBehavior
{
    public static readonly DependencyProperty InstanceProperty =
        DependencyProperty.RegisterAttached("Instance", typeof(object), typeof(PopupRightAlignBehavior), new PropertyMetadata(OnSetInstanceCallback));

    public static object GetInstance(DependencyObject obj)
    {
        return (object)obj.GetValue(InstanceProperty);
    }

    public static void SetInstance(DependencyObject obj, object value)
    {
        obj.SetValue(InstanceProperty, value);
    }

    private static void OnSetInstanceCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var popup = (Popup)d;
        popup.Opened -= OnPopupOpened;
        popup.Opened += OnPopupOpened;
    }

    private static void OnPopupOpened(object sender, System.EventArgs e)
    {
        var popup = (Popup)sender;
        popup.Dispatcher.BeginInvoke(() => popup.HorizontalOffset = -popup.ActualWidth);
    }
}

The Popup control is left-aligned by default. Its left edge is aligned with the left edge of its parent.

What I would like to do is to have the control right-aligned so that its right edge is aligned with the right edge of its container.

I want this to be dynamic because I dynamically bind the data and I don't know how big the popup will be.

I tried playing with the Opened, SizeChanged and Loaded event to get the Child's width and set it to the HorizontalOffset but there seems to be timing issues. Basically it works fine the first time the control is loaded and then never after (the HorizontalOffset is set to 0).

Is this a bug? Am I doing it the wrong way?

EDIT I got it working. It seems that there are timing issues. If I hook up the Opened event and set the HorizontalOffset asynchronously using the Dispatcher, then it works :(

    private static void OnPopupOpened(object sender, System.EventArgs e)
    {
        var popup = (Popup)sender;
        popup.Dispatcher.BeginInvoke(() => popup.HorizontalOffset = -popup.ActualWidth);
    }

EDIT 2 I now realise that I was doing something stupid. I wanted the Popup of the ComboBox to be right-aligned. I didn't see that it was reinitialized in the ArrangePopup private method call.
I tried inheriting from ComboBox to override the placement function but I must be doing something wrong because it still doesn't seem to work although I overrode the methods that call ArrangePopup

Cheers.

解决方案

I now realize that if I don't answer to my own question no one will be able to mark my work-around as an answer. So here's the full code. I implemented it as a PRISM behavior.

public static class PopupRightAlignBehavior
{
    public static readonly DependencyProperty InstanceProperty =
        DependencyProperty.RegisterAttached("Instance", typeof(object), typeof(PopupRightAlignBehavior), new PropertyMetadata(OnSetInstanceCallback));

    public static object GetInstance(DependencyObject obj)
    {
        return (object)obj.GetValue(InstanceProperty);
    }

    public static void SetInstance(DependencyObject obj, object value)
    {
        obj.SetValue(InstanceProperty, value);
    }

    private static void OnSetInstanceCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var popup = (Popup)d;
        popup.Opened -= OnPopupOpened;
        popup.Opened += OnPopupOpened;
    }

    private static void OnPopupOpened(object sender, System.EventArgs e)
    {
        var popup = (Popup)sender;
        popup.Dispatcher.BeginInvoke(() => popup.HorizontalOffset = -popup.ActualWidth);
    }
}

这篇关于动态设置弹出窗口的位置/位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆