ItemsControl 中的 ItemsControl

ItemsControl within ItemsControl

(连续拉了8个小时的头发,我已经放弃了,如果有人能来解救,将不胜感激):

这是我的:

AlbumItem:这是一个 ItemsControl,它使用 Canvas 作为其 ItemsPanel 并绑定到一个集合 属性底层虚拟机。此控件的 Resources 部分中定义的少数 DataTemplate 执行将 ViewModel 对象转换为 UI 对象。此控件工作得非常好,符合预期。

专辑:这又是一个 ItemsControl,它使用 UniformGrid 作为其 ItemsPanel 并绑定到一个集合 属性 底层虚拟机。此控件显示 AlbumItem 的网格。我已将此控件的 ItemTemplate 设置为 AlbumItem

无论我做什么,第二个控件都不会使用它的 ItemTemplate 来显示它的项目。 UniformGrid 效果很好,我得到了一个 3 x 3 的项目网格,但这些项目中的每一个都是一个简单的 TextBlock 显示基础 VM 对象的 class 名称。

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

谁能看出哪里出了问题?

编辑

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

AlbumItem

<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 确认以下内容:

我已经尝试编写模仿您的代码的尽可能小的项目 - 我想我遇到了与您相同的问题并且我的 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 放在可视化(资源)树的较高位置,看看会发生什么。

原来是底层数据源的问题。我将相册与 List<T> 绑定,由于基础 属性 Baked 的以下行,它没有更新 UI 及其项目中的更改:

If _Baked Is value Then Return

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