简体   繁体   English

更改itemscontrol windows phone中元素的zindex

[英]changing zindex of elements in itemscontrol windows phone

This is a question with many different answers, but have not found one working for Windows Phone. 这是一个有许多不同答案的问题,但还没有找到适用于Windows Phone的问题。
So here goes: 所以这里:

I have an Items Control that displays UserControls. 我有一个显示UserControls的Items Control。
I bind an ObservableCollection to this ItemsControl like this: 我将ObservableCollection绑定到此ItemsControl,如下所示:

<Canvas Name="CanvasGrid" Grid.Column="1" Background="Transparent" Canvas.ZIndex="5">
    <ItemsControl ItemsSource="{Binding InGame}">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Canvas>
                    <View:SInGame/>
                </Canvas>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</Canvas>

When an element is added in Itemscontrol the element is given a zindex independent of what I give the element, and the usercontrol which is showed. 当在Itemscontrol中添加一个元素时,该元素被赋予一个独立于我给予该元素的zindex,以及显示的usercontrol。 What I want to do is have to buttons where I can move the selected element up and down in the z direction. 我想要做的是有按钮,我可以在z方向上下移动选定的元素。

View SInGame 查看SInGame

The Canvas inside the itemscontrol is needed for the position to be binded correctly from the following view: 要从以下视图中正确绑定位置,需要使用itemscontrol中的Canvas:

<UserControl x:Class="MVVMTestApp.View.SInGame"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WP8"
xmlns:View="clr-namespace:MVVMTestApp.View"
mc:Ignorable="d"
Canvas.Left="{Binding pos.x}" Canvas.Top="{Binding pos.y}">

<Path >
    <.....
    ....../>
</Path>
</UserControl>

It could then be argued that the view should consist of a Canvas that has the position binded. 然后可以认为视图应该由具有绑定位置的Canvas组成。 But this would still leave the issue of the zindex. 但这仍然会留下zindex的问题。

As stated in the comments. 正如评论中所述。 The ItemsControl cannot see the outside canvas and can therefore not use the zindex to reach that. ItemsControl无法看到外部画布,因此无法使用zindex来实现。 So how is it possible to set the zindex? 那么如何设置zindex呢? Or is it not possible using the ItemsControl element? 或者使用ItemsControl元素是不可能的?

The ItemsControl takes each item, wraps it in a container (ContentPresenter), and adds it to the items panel (StackPanel by default). ItemsControl获取每个项目,将其包装在容器(ContentPresenter)中,并将其添加到项目面板(默认情况下为StackPanel)。 So, schematically, you will end up with this tree: 因此,示意性地,您将最终获得此树:

<!-- the items panel (StackPanel by default) -->
<StackPanel>
    <!-- the first item wrapper -->
    <ContentPresenter>
        <!-- your item template -->
        <Canvas>
            <View:SInGame/>
        </Canvas>
    </ContentPresenter>

    <!-- more items ... -->
</StackPanel>

You will want to do 2 things: 你会想要做两件事:

  • Set ItemsControl.ItemsPanel to give the items a shared Canvas container. 设置ItemsControl.ItemsPanel为项目提供共享的Canvas容器。
  • Make sure that the ZIndex you want gets applied to the ContentPresenter wrappers. 确保您想要的ZIndex应用于ContentPresenter包装器。

These two points will give you a schema like this, which should allow you to position the items front-to-back: 这两点将为您提供这样的架构,这应该允许您从前到后定位项目:

<!-- the items panel (change to a Canvas) -->
<Canvas>
    <!-- the first item wrapper (need to set Canvas.ZIndex to position) -->
    <ContentPresenter Canvas.ZIndex="1">
        <!-- your item template -->
        <Canvas>
            <View:SInGame/>
        </Canvas>
    </ContentPresenter>

    <!-- more items ... -->
</Canvas>

To achieve the second point, I believe you will need to subclass ItemsControl , and override PrepareContainerForItemOverride . 为了达到第二点,我相信你需要子类ItemsControl ,并重写PrepareContainerForItemOverride For example, the following modifies each item container, binding its ZIndex property to the ZIndex of the item itself: 例如,以下内容修改每个项容器,将其ZIndex属性绑定到项本身的ZIndex:

public class CanvasItemsControl : ItemsControl
{
    protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
    {
        base.PrepareContainerForItemOverride(element, item);
        var contentPresenter = (ContentPresenter)element;
        var binding = new Binding("ZIndex") { Source = contentPresenter.Content };
        contentPresenter.SetBinding(Canvas.ZIndexProperty, binding);
    }
}

Now you can just bind Canvas.ZIndex on the View:SInGame item to the underlying model property ("pos.x"?). 现在,你可以绑定Canvas.ZIndexView:SInGame项目底层模型属性(“pos.x”?)。

Putting it all together: 把它们放在一起:

<local:CanvasItemsControl ItemsSource="{Binding InGame}">
    <local:CanvasItemsControl.ItemTemplate>
        <DataTemplate>
            <Canvas Canvas.ZIndex="{Binding pos.x}" >
                <View:SInGame />
            </Canvas>
        </DataTemplate>
    </local:CanvasItemsControl.ItemTemplate>
    <local:CanvasItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas />
        </ItemsPanelTemplate>
    <local:CanvasItemsControl.ItemsPanel>
</local:CanvasItemsControl>

This way, each SInGame instance gets a Z-index, and each should be positioned relative to the others. 这样,每个SInGame实例都获得一个Z-index,每个实例都应该相对于其他实例定位。 You can re-position the items front-to-back by modifying the "MyZIndex" property of each view-model item in "InGame". 您可以通过修改“InGame”中每个视图模型项的“MyZIndex”属性来前后重新定位项目。


Edit 编辑

There's a simpler alternative to the above, which might work for you. 上面有一个更简单的替代方案,可能对你有用。 This approach will give you a flattened tree like this: 这种方法会给你一个扁平的树,如下所示:

<!-- the items panel (change to a Canvas) -->
<Canvas>
    <!-- the items -->
    <View:SInGame/>
    <View:SInGame/>
</Canvas>

To do this, override GetContainerForItemOverride() to return the SInGame object: 为此,重写GetContainerForItemOverride()以返回SInGame对象:

public class CanvasItemsControl : ItemsControl
{
    protected override DependencyObject GetContainerForItemOverride()
    {
        return new SInGame();
    }

    // Any setup of the `SInGame` items should be done here
    protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
    {
        base.PrepareContainerForItemOverride(element, item);
        var container = (SInGame)element;
    }
}

This allows you to define the ItemsControl without any ItemTemplate: 这允许您在没有任何ItemTemplate的情况下定义ItemsControl:

<local:CanvasItemsControl ItemsSource="{Binding InGame}">
    <local:CanvasItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas />
        </ItemsPanelTemplate>
    <local:CanvasItemsControl.ItemsPanel>
</local:CanvasItemsControl>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM