Wpf 置于前面

发布于 2024-09-14 10:21:46 字数 989 浏览 3 评论 0原文

我有一个 ItemsControl,它与 ItemsPanel 一样使用 Canvas。 itemsTemplate 托管一个自定义控件。单击控件时,我希望它“移到前面”。我知道我可以使用我的控件中的 ZIndex 来做到这一点,如下所示:

 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 个控件,它们的 ZIndex 都为 0。(因此它们使用默认列表位置。)

如果我单击控件 3,然后单击控件 2,然后单击控件 1。我希望它的顶部有 3 ZOrder,然后是 2,然后是 1。但是由于我在 MouseUp 上将 ZIndex 设置为零,因此默认顺序为 1,2,3。

有没有一种简单的方法来处理这个问题,或者我是否需要自己跟踪顺序并递增或递减任意值(例如 99)?

I have a ItemsControl which uses a Canvas as as as the ItemsPanel. The itemsTemplate hosts a Custom Control. When the control is clicked I would like it to "move to the front". I know I can do this with the ZIndex in my control like so:

 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);
}

This works and sets the ZIndex just fine. But when I click on a different control in the ItemsControl it will get the exact same ZIndex so it will not "move in front" of the other control.

Basically I just want the same behavior as windows exhibit.

I've tried setting the ZIndex back to 0 in the PreviewMouseUp event, and that ensures that the clicked control is always at the top, but then since all other controls have the same ZIndex of 0 then will assume default order based on there position in the list.

An example:

Lets say I have 3 controls all with a ZIndex of 0. (so they use the default list position.)

If I click on control 3, then 2 then 1. I would expect it to have 3 at the top of the ZOrder, then 2 then 1. But since I'm setting the ZIndex to zero on MouseUp it would have the default order of 1,2,3.

Is there an easy way to handle this or do I need to keep track of the order and increment decrement an arbitrary value such as 99 on my own?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

三月梨花 2024-09-21 10:21:46

我会按照这些思路做一些事情:

当鼠标按下时,将所选控件上的 Z 索引设置为非常高的数字。
将 static int Zindex 初始化为 0。
鼠标抬起时,将 Z-index 设置为等于 Zindex++

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-index 并从 z-index 中减去该上限所有控件的索引和 Zindex 计数器。

I would do something along these lines:

Upon mouse down set the Z-index on the selected control to a very high number.
Have a static int Zindex initialized to 0.
Upon mouse up set the Z-index equal to Zindex++

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++);
}

If your program should be running for a long time you could have some upper limit on Zorder, so if reached you could find the smallest z-index in use and substract this from the z-index on all controls and the Zindex counter.

沦落红尘 2024-09-21 10:21:46

就我而言,我在选定的控件上设置 Zindex,然后枚举所有其他控件并在需要时增加其 ZIndex,因为在某些时候您可能会遇到选定的控件,而所有其他控件都不需要更改。

丑陋,但到目前为止我没有更好的解决方案

In my case I set Zindex on selected control and then enumerate all other controls and increment their ZIndex if needed, since at some point you can encounter selected control and all others doen't need to be changed.

Ugly, but so far I have no better solution

放我走吧 2024-09-21 10:21:46

最简单的方法是仅枚举所有项目一次,并且仅在我们通过了要放在前面的项目时才减少 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 属性。

The easiest way is to enumerate all items just once and only decrease the z-index if we've passed the one to bring to the front. This ensures the z-index of the bottom-most item always has a z-index of 0 and the last item a z-index of (count - 1), with each differing by an integer of 1.

If you increase (or decrease) each one every time, setting the one to bring to front with highest, the z-index may never start at 0 and the ultimate result might be too counter-intuitive for your liking.

So whenever an item should be brought to the front, you can enumerate the items like this:

//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;
}

This assumes you bind a list of your objects to an ItemsControl and the objects have a Z property that binds to Panel.ZIndex property in the ItemContainerStyle.

帅哥哥的热头脑 2024-09-21 10:21:46

我有类似的情况,但当鼠标悬停在控件上时,我需要将该项目置于前面。我找到了一个更简单的问题解决方案:只需通过触发器在 ItemsControl.ItemContainerStyle 中设置 Panel.ZIndex 即可。

这也可以使用绑定到 viewModel 中标志的 DataTrigger,例如单击控件时设置的 IsSelected 属性。

            <ItemsControl Name="ScanPoints" ItemsSource="{Binding ScanPoints}">
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <Canvas></Canvas>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
                <ItemsControl.ItemContainerStyle>
                    <Style TargetType="ContentPresenter">
                        <Style.Triggers>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter Property="Panel.ZIndex" Value="99999"/>
                            </Trigger>
                            <Trigger Property="IsMouseOver" Value="False">
                                <Setter Property="Panel.ZIndex" Value="0"/>
                            </Trigger>                            
                        </Style.Triggers> 
                    </Style>
                </ItemsControl.ItemContainerStyle>
            </ItemsControl>

I have a similar situation but I need to bring the item to front when the mouse hovers over the control. I have found a much simpler solution to the problem: simply set the Panel.ZIndex in the ItemsControl.ItemContainerStyle via a trigger.

This could also use a DataTrigger that is bound to a flag in the viewModel, for example an IsSelected property that is set when the control is clicked.

            <ItemsControl Name="ScanPoints" ItemsSource="{Binding ScanPoints}">
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <Canvas></Canvas>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
                <ItemsControl.ItemContainerStyle>
                    <Style TargetType="ContentPresenter">
                        <Style.Triggers>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter Property="Panel.ZIndex" Value="99999"/>
                            </Trigger>
                            <Trigger Property="IsMouseOver" Value="False">
                                <Setter Property="Panel.ZIndex" Value="0"/>
                            </Trigger>                            
                        </Style.Triggers> 
                    </Style>
                </ItemsControl.ItemContainerStyle>
            </ItemsControl>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文