解決 Popup 位置不隨視窗移動更新的問題

2021-09-07 18:28:46 字數 4489 閱讀 3870

原文:

解決 popup 位置不隨視窗移動更新的問題

popup彈出後,因業務需求設定了staysopen=true後,移動視窗位置或者改變視窗大小,popup的位置不會更新。

如何更新位置?

獲取當前popup的target繫結usercontrol所在視窗,位置重新整理時,時時更新popup的位置即可。

1.新增乙個附加屬性

1

///2

///popup位置更新

3///

4public

static

readonly dependencyproperty popupplacementtargetproperty =

5 dependencyproperty.registerattached("

popupplacementtarget

", typeof(dependencyobject), typeof(popuphelper), new propertymetadata(null, onpopupplacementtargetchanged));

2.視窗移動後觸發popup更新

首先,有個疑問,popup首次顯示時,為何顯示的位置是正確的呢?

通過檢視原始碼,發現,其實popup也是有內建更新popup位置的!

而通過檢視updateposition**,其方法確實是更新popup位置的。原始碼如下:

1

private

void

updateposition()226

else

27 num4 =popup.getnumberofcombinations(placement);

28for (int i = 0; i < num4; ++i)

2939

else

4048 rect rect2 =rect.offset(rect1, offsetvector2);

49 rect rect3 = rect.intersect(this.getscreenbounds(bounds, targetinterestpoints[0

]), rect2);

50double num5 = rect3 != rect.empty ? rect3.width * rect3.height : 0.0;51

if (num5 - num3 > 0.01)52

62}63if (num2 >= 2 && (placement == placementmode.right || placement ==placementmode.left))

64this.dropopposite = !this

.dropopposite;

65 rect1 = new rect((size)this._sechelper.gettransformtodevice().transform((point)this

._popuproot.value.rendersize));

66rect1.offset(offsetvector1);

67 rect screenbounds = this.getscreenbounds(bounds, targetinterestpoints[0

]);68 rect rect4 =rect.intersect(screenbounds, rect1);

69if (math.abs(rect4.width - rect1.width) > 0.01 || math.abs(rect4.height - rect1.height) > 0.01)70

81else

if (this.istransparent && math.abs(vector1.x) < 0.01)82

88 point point2 = targetinterestpoints[2

];89 vector vector2 = point1 -point2;

90vector2.normalize();

91if (!this.istransparent || double.isnan(vector2.x) || math.abs(vector2.x) < 0.01)92

98else

if (this.istransparent && math.abs(vector2.y) < 0.01)99

105}

106int x =doubleutil.doubletoint(offsetvector1.x);

107int y =doubleutil.doubletoint(offsetvector1.y);

108if (x == this._positioninfo.x && y == this

._positioninfo.y)

109return

;110

this._positioninfo.x =x;

111this._positioninfo.y =y;

112this._sechelper.setpopuppos(true, x, y, false, 0, 0

);113 }

view code

那麼,我們有什麼辦法呼叫這個私有方法呢?我相信大家都想,找到popup原始碼開發者,爆了他y的!

有一種方法,叫反射,反射可以獲取類的任乙個字段或者屬性。

反射,可以參考:

通過反射,我們獲取到updateposition方法,並呼叫執行。

1

var mi = typeof(popup).getmethod("

updateposition

", bindingflags.nonpublic |bindingflags.instance);

2 mi.invoke(pop, null);

下面是詳細的屬性更改事件實現:

1

private

static

void

onpopupplacementtargetchanged(dependencyobject d, dependencypropertychangedeventargs e)213

}1415//

新值新增locationchanged監聽

16if (e.newvalue is

dependencyobject newplacementtarget)

1724}25

void windowlocationchanged(object

s1, eventargs e1)

2633

}34 }

值得注意的是,原有的繫結目標源要記得取消locationchanged事件訂閱,新的繫結目標源保險起見,也要提前登出再新增事件訂閱。

另:通知popup位置更新,也可能通過如下的黑科技:

1

//通知更新相對位置

2var offset =pop.horizontaloffset;

3 pop.horizontaloffset = offset + 1

;4 pop.horizontaloffset = offset;

為何改變一下horizontaloffset就可行呢?因為上面最終並沒有改變horizontaloffset的值。。。

原來。。。好吧,先看原始碼

1

///獲取或設定目標原點和彈出項對齊之間的水平距離點。

2///

3///

目標原點和 popup 對齊點之間的水平距離。

4///

有關目標原點和 popup 對齊點的資訊,請參閱 popup 放置行為。

5///

預設值為 0。

6///

7 [bindable(true

)]8 [category("

layout")]

9 [typeconverter(typeof

(lengthconverter))]

10public

double

horizontaloffset

1116

set1720}

2122

private

static

void

onoffsetchanged(dependencyobject d, dependencypropertychangedeventargs e)

23

是的,最終呼叫了reposition,而reposition方法中有呼叫updateposition更新popup位置。

所以以上,更新horizontaloffset,是更新popup位置的一種捷徑。

***xx

拖動視窗任意位置移動視窗 網上找的沒有整理

除了拖動標題欄移動視窗以外,我們也可以拖動視窗任意位置 除控制項 位置而使對話方塊移動。這裡只講述基於對話方塊的程式 首先在對話方塊類中定義幾個變數 class c dlg public cdialog 新增onmousemove訊息響應函式 void c dlg onmousemove uint ...

解決 OIM910 移動安裝位置後無法正常啟動

軟體名稱 oralce identity management 910 安裝環境 jboss 4.23 ga oralce database 10g r2 安裝位置 c oim910 新位置 d oim910 問題 一開始安裝在c盤,後來移到d盤,啟動jboss的時候,可以正常連線去database...

網路遊戲位置移動同步 「時延」 問題的解決

情景假設 a 客戶端傳送位置移動訊息 包括當前位置和當前速度 經過伺服器 s 發到客戶端 b,因為網路延遲而造成客戶端 b 接收到訊息時,客戶端又移動了一定的距離,所以此時 b 客戶端從 a 傳送的位置開始按照a傳送的速度開始移動,這就出現了位置的不同步 解決方法 我們只要在傳送資料時將 傳送時間 ...