【问题标题】:ItemsControl within ItemsControlItemsControl 中的 ItemsControl
【发布时间】:2015-09-15 13:38:13
【问题描述】:

连续拔了8个小时头发,我放弃了。如果有人能来救援,将不胜感激):

这是我所拥有的:

AlbumItem:这是一个ItemsControl,它使用Canvas 作为其ItemsPanel,并绑定到基础VM 的集合属性。在此控件的Resources 部分中定义的少数DataTemplates 将 ViewModel 对象转换为 UI 对象。此控件运行良好,符合预期。

相册:这又是一个ItemsControl,它使用UniformGrid 作为其ItemsPanel,并绑定到基础VM 的集合属性。此控件显示AlbumItems 的网格。我已将此控件的ItemTemplate 设置为AlbumItem

无论我做什么,第二个控件都不会使用它的ItemTemplate 来显示它的项目。 UniformGrid 工作得很好,我得到了一个 3 x 3 网格的项目,但每个项目都是一个简单的 TextBlock 显示底层 VM 对象的类名。

我也尝试使用DataTemplate,而不是使用ItemTemplate,但无济于事。

谁能看出哪里出错了?

编辑

发布一个工作示例将是一项艰巨的任务(这是一个复杂的项目),但我可以在这里发布相关的 XAML:

专辑项目

<ItemsControl x:Class="AlbumItem" 
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:bd="clr-namespace:ViewProject" 
         xmlns:vm="clr-namespace:ViewModelProject" 
         mc:Ignorable="d" 
         ItemsSource="{Binding Path=Children}"
         ClipToBounds="True" Background="LightYellow">
<ItemsControl.Resources>
  <BooleanToVisibilityConverter x:Key="B2VConverter" />
  <DataTemplate DataType="{x:Type vm:Ellipse}">
    <Ellipse IsHitTestVisible="False" StrokeThickness="{Binding BorderThickness}" Fill="{Binding Fill, Mode=OneWay}" Stroke="{Binding Stroke, Mode=OneWay}" />
  </DataTemplate>  
</ItemsControl.Resources>
<ItemsControl.ItemsPanel>
   <ItemsPanelTemplate>
     <Canvas HorizontalAlignment="Left" VerticalAlignment="Top" Focusable="true" Width="{Binding Size.Width}" Height="{Binding Size.Height}" FocusVisualStyle="{x:Null}">
     </Canvas>
   </ItemsPanelTemplate>
 </ItemsControl.ItemsPanel>
 <ItemsControl.ItemContainerStyle>
    <Style>
      <Setter Property="Canvas.Left" Value="{Binding Path=Location.X}" />
      <Setter Property="Canvas.Top" Value="{Binding Path=Location.Y}" />
      <Setter Property="Panel.ZIndex" Value="{Binding Path=GlobalZOrder}" />
    </Style>
  </ItemsControl.ItemContainerStyle>
</ItemsControl>

专辑

<ItemsControl x:Class="Album"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" 
         xmlns:bd="clr-namespace:ViewProject" 
         xmlns:vm="clr-namespace:ViewModelProject" 
         d:DesignHeight="500" d:DesignWidth="800"
         ItemsSource="{Binding Drawing.Baked}" 
         ClipToBounds="True">

  <ItemsControl.ItemsPanel>
    <ItemsPanelTemplate>
      <UniformGrid Rows="3" Columns="3" />
    </ItemsPanelTemplate>
  </ItemsControl.ItemsPanel>
  <ItemsControl.ItemTemplate>
    <DataTemplate DataType="vm:ReadonlyDrawingVM">
      <bd:AlbumItem />
    </DataTemplate>
  </ItemsControl.ItemTemplate>
</ItemsControl>

我已使用 Snoop 确认以下内容:

  • 相册的DataContext 是正确的。它的ItemsSource 也是如此。当我深入研究ItemsSource 时,我实际上可以看到 Snoop 中的所有 VM 对象。
  • 默认情况下,相册根本不显示任何内容。如果我使用 Snoop 重置专辑的 ItemTemplate 和/或 ItemsPanel 属性,我会根据我重置的属性以网格或列表的形式看到所有项目(即带有类名的 TextBlock)。
  • AlbumItem 可以很好地处理设计时 XML 数据。专辑没有。

【问题讨论】:

  • 发布 XAML 代码和用于绑定到数据的代码。任何数量的事情都可能是错误的,例如不正确的 XAML、不正确的绑定、提供任何要绑定的 AlbumItems、使用错误的绑定语法绑定到 AlbumItems
  • 是的,我们需要看看幕后花花公子。
  • 我建议您创建一个类似的测试项目来模拟问题并发布...通过提供数据/xaml 这将增加某人提供答案的机会或练习将揭示问题从头开始给建筑师。
  • @PanagiotisKanavos:抱歉,我不得不离开办公桌。请检查我的编辑。我添加了一堆相关的 XAML 代码。
  • 假设 Album 正在设置您的 DataContext,并且您的 AlbumItem 位于 DataTemplate 中,您可以通过 {Binding Path=Children.DataContext, ElementName=Album} 之类的操作来联系它吗?

标签: .net wpf xaml datatemplate itemscontrol


【解决方案1】:

我试图编写尽可能小的项目来模仿你的代码 - 我想我遇到了和你一样的问题,我为我的 AlbumItem VM 获得了 TextBlocks。

对我来说,我正在努力在 AlbumItem 中使用 ItemsControl.ItemTemplate,但直接使用 - 不是通过 ItemsControl.Resources。经过一些实验,用于 AlbumItems 的 ContentPresenter 似乎找不到 VM 的默认 DataTemplate。

<ItemsControl x:Class="so_wpf_32587588.AlbumItemView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:soWpf32587588="clr-namespace:so_wpf_32587588">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas Width="100" Height="100" FocusVisualStyle="{x:Null}" IsItemsHost="True"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemContainerStyle>
        <Style TargetType="ContentPresenter">
            <Setter Property="Canvas.Left" Value="{Binding Path=X}"/>
            <Setter Property="Canvas.Top" Value="{Binding Path=Y}"/>
            <Setter Property="Panel.ZIndex" Value="{Binding ZOrder}"/>
        </Style>
    </ItemsControl.ItemContainerStyle>
    <ItemsControl.ItemTemplate>
        <DataTemplate DataType="soWpf32587588:AlbumItemView">
            <Rectangle Width="40" Height="40" Fill="{Binding ItemBrush}"/>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

我在编写某种自定义 ResourceDictionary 时遇到了类似的问题 - 我发现字典已经被解析,但在 ResourceDictionary 使用的哈希中不可用,因此任何需要资源的控件都只能获得默认资源而不是定义的资源。

您可以尝试将 DataTemplate 放在可视(资源)树的较高位置,看看会发生什么。

【讨论】:

    【解决方案2】:

    这原来是由于底层数据源。我将 Album 与 List&lt;T&gt; 绑定,由于基础属性 Baked 的以下行,它没有使用其项目的更改更新 UI:

    If _Baked Is value Then Return
    

    这是Baked 属性设置器中的第一行(我使用的是 MVVM Light 提供的默认属性模板)。因为我从来没有给_Baked分配一个新的List&lt;T&gt;;仅更改其中的项目,上述行将停止引发属性更改通知。一旦我解决了这个问题,我的相册就开始被填充。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-24
      • 2011-04-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多