原文:
解決 popup 位置不隨視窗移動更新的問題
popup彈出後,因業務需求設定了staysopen=true後,移動視窗位置或者改變視窗大小,popup的位置不會更新。
如何更新位置?
獲取當前popup的target繫結usercontrol所在視窗,位置重新整理時,時時更新popup的位置即可。
1.新增乙個附加屬性
12.視窗移動後觸發popup更新///2
///popup位置更新
3///
4public
static
readonly dependencyproperty popupplacementtargetproperty =
5 dependencyproperty.registerattached("
popupplacementtarget
", typeof(dependencyobject), typeof(popuphelper), new propertymetadata(null, onpopupplacementtargetchanged));
首先,有個疑問,popup首次顯示時,為何顯示的位置是正確的呢?
通過檢視原始碼,發現,其實popup也是有內建更新popup位置的!
而通過檢視updateposition**,其方法確實是更新popup位置的。原始碼如下:
1view codeprivate
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 }
那麼,我們有什麼辦法呼叫這個私有方法呢?我相信大家都想,找到popup原始碼開發者,爆了他y的!
有一種方法,叫反射,反射可以獲取類的任乙個字段或者屬性。
反射,可以參考:
通過反射,我們獲取到updateposition方法,並呼叫執行。
1下面是詳細的屬性更改事件實現:var mi = typeof(popup).getmethod("
updateposition
", bindingflags.nonpublic |bindingflags.instance);
2 mi.invoke(pop, null);
1值得注意的是,原有的繫結目標源要記得取消locationchanged事件訂閱,新的繫結目標源保險起見,也要提前登出再新增事件訂閱。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 }
另:通知popup位置更新,也可能通過如下的黑科技:
1為何改變一下horizontaloffset就可行呢?因為上面最終並沒有改變horizontaloffset的值。。。//通知更新相對位置
2var offset =pop.horizontaloffset;
3 pop.horizontaloffset = offset + 1
;4 pop.horizontaloffset = offset;
原來。。。好吧,先看原始碼
1是的,最終呼叫了reposition,而reposition方法中有呼叫updateposition更新popup位置。///獲取或設定目標原點和彈出項對齊之間的水平距離點。
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
所以以上,更新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傳送的速度開始移動,這就出現了位置的不同步 解決方法 我們只要在傳送資料時將 傳送時間 ...