2010-08-11 45 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属性。