2010-08-11 41 views
2

我有一個ItemsControl使用一個Canvas作爲ItemsPanel。 itemsTemplate託管一個自定義控件。點擊控件時,我希望它「移動到前面」。我知道我可以在我的控制與zIndex的做到這一點,像這樣:Wpf帶到前面

private void MyControl_PreviewMouseDown(object sender, MouseButtonEventArgs e) 
{ 
    if(((FrameworkElement)sender).TemplatedParent==null) return; 
    ContentPresenter presenter = (ContentPresenter)((FrameworkElement) sender).TemplatedParent; 

    int currentValue = Panel.GetZIndex(presenter); 
    Console.WriteLine(currentValue); 
    Panel.SetZIndex(presenter, 99); 
} 

這個工作並設置zIndex的就好了。但是當我在ItemsControl中點擊不同的控件時,它將得到完全相同的ZIndex,因此它不會「移到其他控件的前面」。

基本上我只是想與Windows展覽一樣的行爲。

我試着在PreviewMouseUp事件中設置ZIndex回到0,並且確保點擊的控件總是在頂部,但是因爲所有其他控件具有相同的ZIndex爲0,那麼將假設基於默認的順序在列表中的位置。

一個例子:

可以說我有3個控制所有爲0的zIndex的

如果我點擊控制3,然後2然後1(所以他們使用默認的列表中的位置)。我期望它在ZOrder的頂部有3個,然後是2然後是1.但是因爲我在MouseUp上將ZIndex設置爲零,所以它的默認順序是1,2,3。

有沒有一種簡單的方法來處理這個問題,還是我需要跟蹤訂單並遞增遞減一個任意值,例如99我自己?

回答

5

我會做這些方針的東西:

當鼠標選擇器上的Z-指數下跌設置爲一個非常高的數字。 有一個靜態INT zIndex的初始化爲0 當鼠標向上設置Z-索引等於Z-索引++

private static int Zindex = 0; 

private void MyControl_PreviewMouseDown(object sender, MouseButtonEventArgs e) 
{ 
    if(((FrameworkElement)sender).TemplatedParent==null) return; 
    ContentPresenter presenter = (ContentPresenter)((FrameworkElement) sender).TemplatedParent; 

    int currentValue = Panel.GetZIndex(presenter); 
    Console.WriteLine(currentValue); 
    Panel.SetZIndex(presenter, Int32.MaxValue); 
} 

private void MyControl_PreviewMouseUp(object sender, MouseButtonEventArgs e) 
{ 
    if(((FrameworkElement)sender).TemplatedParent==null) return; 
    ContentPresenter presenter = (ContentPresenter)((FrameworkElement) sender).TemplatedParent; 

    int currentValue = Panel.GetZIndex(presenter); 
    Console.WriteLine(currentValue); 
    Panel.SetZIndex(presenter, Zindex++); 
} 

如果你的程序應該是運行很長一段時間,你會對ZORDER一定的上限,所以如果達到了你可以找到使用的最小Z指數,並從所有控制和Zindex計數器的Z指數中減去它。

+1

那麼爲了溢出'ZIndex',你需要'int.MaxValue'點擊,即使有人以每秒10次,每天24次的令人難以置信的速度點擊,這仍需要將近7年的連續時間,不間斷的超級點擊!所以我不認爲有什麼可擔心的。另外,靜態成員'ZIndex'的初始值不應該爲'0',因爲第一次點擊會分配'1',這可能低於另一個控件的'ZIndex'。最好用'1000'來初始化它,以確保這種方法從第一次點擊開始就起作用。 – 2012-12-25 15:23:09

+0

輝煌。這也適用於我(略有不同)的情況。我刪除了每個函數開頭的if()檢查,並將演示者更改爲聲明爲:ContentControl presenter =(ContentControl)((FrameworkElement)sender);'。感謝您的解決方案! – Zyre 2015-11-29 16:58:21

0

在我的情況下,我在所選控件上設置Zindex,然後枚舉所有其他控件並根據需要增加它們的ZIndex,因爲在某些時候您可能遇到選定的控件,而其他所有控件都不需要更改。

醜陋,但到目前爲止,我沒有更好的解決辦法

+0

是的,我以前做過這件事,但在這種情況下,我的控件沒有提及託管它的控件。這一切都是通過使用MVVM進行數據綁定完成的。我寧願保持控制封裝。 – Kelly 2010-08-11 23:25:46

0

最簡單的方法是隻枚舉一次所有項目,並且只有在我們通過了一個前導符時才減少z-index。這確保最底部項目的Z索引始終具有Z索引0和最後一個項目Z索引(count-1),其中每個項目的差值都是1的整數。

如果你每次增加(或減少)每一個,將其設置爲最高,z-index可能永遠不會從0開始,最終的結果可能與您的喜好相反。

所以每當一個項目應該被帶到前面,你可以列舉的項目是這樣的:

//If you don't already have the z-index of the item to bring to front (or target item)... 
var i = YourItem.Z; 
foreach (var j in YourListOfItems) 
{ 
    //Current item occurs after target item in sequence 
    if (j.Z > i) 
    { 
     j.Z--; 
    } 
    else if (j.Z < i) 
    { 
     //Curent item occurs before target item in sequence; no need to change the z-index 
    } 
    else j.Z = YourListOfItems.Count - 1; 
} 

這裏假設你的對象列表綁定到ItemsControl和對象都有一個Z屬性,綁定到ItemContainerStyle中的Panel.ZIndex屬性。