2014-04-18 25 views
3

這是一個有很多不同答案的問題,但還沒有找到一個適用於Windows Phone的問題。
所以這裏去:更改項目控件窗口中元素的zindex手機

我有一個項目控件,顯示UserControls。
我一個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> 

當元件被在ItemsControl中添加給出的是我給元件的Z-索引獨立的元件,並且其顯示出該用戶控件。我想要做的是必須按鈕,我可以在z方向上上下移動選定的元素。

查看SInGame

需要ItemsControl的內部畫布上的位置,以正確地從下面的視圖來綁定:

<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> 

它可能然後可以說,認爲應包括的具有綁定位置的畫布。但是這仍然會導致zindex的問題。

正如評論中所述。 ItemsControl無法看到外部畫布,因此不能使用zindex來達到此目的。那麼如何設置zindex?或者是否不可能使用ItemsControl元素?

+0

刪除ItemsControl的DataTemplate中的Canvas。有另一個畫布會混淆ZIndex的渲染。之後,我相信你可以將ZIndex綁定到實體的屬性(InGame集合中的項目) –

+0

@ShawnKendrot沒有畫布的元素不呈現,所以這是不可能的? – JTIM

+0

當然它會被渲染。 ItemsControl不需要Canvas在DataTemplate中 –

回答

2

ItemsControl將每個項目都包裝在一個容器(ContentPresenter)中,並將其添加到項目面板(默認情況下爲StackPanel)。所以,示意地,你將最終獲得這棵樹:

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

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

你會想要做兩件事情:

  • 設置ItemsControl.ItemsPanel給予項目共享Canvas容器。
  • 確保您想要的ZIndex適用於ContentPresenter包裝。

這兩點會給你這樣一個架構,它應該讓你從前至後位置的項目:

<!-- 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> 

爲了實現第二點,我相信你會需要子類ItemsControl,並覆蓋PrepareContainerForItemOverride。例如,下面的修改每個項目的容器,其zIndex屬性綁定到項目本身的Z-索引:

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

現在,你可以在View:SInGame項目綁定Canvas.ZIndex底層模型屬性(「pos.x」 ?)。

全部放在一起:

<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> 

這樣,每個SInGame實例都有一個Z-索引,每個應當相對於其他位置。您可以通過修改「InGame」中每個視圖模型項目的「MyZIndex」屬性來重新定位項目。


編輯

有一個簡單的選擇上面,這可能會爲你工作。這種方法會給你一個扁平的樹是這樣的:

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

要做到這一點,覆蓋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; 
    } 
} 

這允許您定義的ItemsControl沒有任何的ItemTemplate:

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

謝謝,當我有時間並回報時,我會在這個星期五進行測試。但是,謝謝你的詳細解答! – JTIM

+0

我猜數據模板中的Canvas是不需要的。在這種情況下,我們使用帶有SInGame的Canvas的ContentPresenters畫布。有點複雜是不是? – ad1Dima

+0

@ad1Dima再次查看OP - SInGame控件定義了Canvas.Left。這隻會在其直接父母是帆布... – McGarnagle

相關問題