ItemsControl 仅显示第一项

发布于 2024-11-15 09:38:17 字数 3648 浏览 4 评论 0原文

我怀疑我的问题的答案非常简单,但我仔细浏览了论坛,似乎找不到任何完全相同的内容。

我有一个相当复杂的绑定结构,远端有一个 ItemsControl,但它只显示第一个项目。我可以看到代码端的数据是正确的,仅包含 8 个项目,第一个项目正确显示,并根据需要提供所有标签和颜色。

逻辑侧结构如下:

  • MainWindow Partial Class
    • WaterSamplerClass 的 ObservableCollection
      • ParametersClass(类的单个实例)
        • bottleStateClass 的 ObservableCollection
          • int 数字(属性)
          • 字符串标签(属性)

XAML结构如下:

  • MainWindow Partial Class
    • ControlTemplate GroupBox(代码中设置的列表中的 DataContext WaterSampler 实例)
      • 包含使用 BottleState 控件模板的按钮的 DataTemplate
      • ItemsControl 使用 DataTemplate 显示大量 BottleState
    • 包含 ItemsControl 中使用的 Button 装饰的 ControlTemplate

下面是代码的简化版本:

Items 控件及其在 GroupBox ControlTemplate 中的数据模板datacontext 是 WaterSampler 的一个实例。

<ControlTemplate x:Key="WaterSamplerGroupBoxTemplate" TargetType="{x:Type GroupBox}" >
   <GroupBox Header="{Binding Path=Header}" Width="300" Margin="10,5,10,0" HorizontalAlignment="Center">
    <StackPanel Orientation="Horizontal">
      <StackPanel.Resources>
         <DataTemplate x:Key="BottleStateDataTemplate">
               <Button Template="{DynamicResource ValveStatusTemplate}" />
         </DataTemplate>
      </StackPanel.Resources>
    <ItemsControl Name="bottleStateListBox" ItemTemplate="{StaticResource BottleStateDataTemplate}" Margin="5" Height="50" ItemsSource="{Binding BottleIsFullList}" DataContext="{Binding Parameters}"/>
    </StackPanel>
  </GroupBox>
</ControlTemplate>

简化的按钮控件模板:

<ControlTemplate x:Key="ValveStatusTemplate" TargetType="{x:Type Button}" >
      <StackPanel Orientation="Vertical" Width="30" Margin="5" >           
           <TextBlock Text="{Binding Number}" FontSize="18" Canvas.Left="8"/>
      </StackPanel>
</ControlTemplate>

保存项目模板数据的类:

public class DisplayBottleStateClass : INotifyPropertyChanged
{
    private int number;
    public int Number
    {
        get { return number; }
    }
}

包含 DisplayBottleClass 列表的类:

public class WSParametersClass : INotifyPropertyChanged
{
    private List<DisplayBottleStateClass> bottleIsFullList = new List<DisplayBottleStateClass>();

    public List<DisplayBottleStateClass> BottleIsFullList
    {
        get { return bottleIsFullList; }
    }
}

包含参数的类:

public class WaterSampler : INotifyPropertyChanged
{
    private WSParametersClass parameters = new WSParametersClass();

    public WSParametersClass Parameters
    {
        get { return parameters; }
        set { parameters = value; OnPropertyChanged("Parameters"); }
    }
}

最后 MainWindow 类:

public partial class MainWindow : Window
{
    public class WaterSamplerListClass : ObservableCollection<WaterSampler> { }
    private WaterSamplerListClass waterSamplers = new WaterSamplerListClass();
    public MainWindow()
    {
        waterSamplers.Add(new WaterSampler(0));
        WaterSampler0Group.DataContext = (waterSamplers[0]);
    }
}

我使用的两个画笔确实遇到了绑定错误但是当我用 XAML 中的固定值替换它们时,仍然只显示第一个元素。该列表似乎也通过绑定正确更新,因为我可以看到第一个元素正确更改。我得到的错误是:

System.Windows.Data 错误:2:找不到目标元素的管理 FrameworkElement 或 FrameworkContentElement。 BindingExpression:Path=GradientStopHighlight;数据项=空;目标元素是“GradientStop”(HashCode=23577486);目标属性是“颜色”(类型“颜色”)

任何建议将非常受欢迎。

非常感谢

艾德

I suspect the answer to my problem is pretty simple but I have had a good look around the forum and can't seem to find anything quite the same.

I have a reasonably complex binding structure with a ItemsControl at the far end but it only shows the first item. I can see the data on the code side is correct and holds only 8 items, the first item is displayed correctly with all labeling and colours as required.

The logic side structure is like:

  • MainWindow Partial Class
    • ObservableCollection of WaterSamplerClass
      • ParametersClass (single instance of a class)
        • ObservableCollection of bottleStateClass
          • int Number (Property)
          • string Label (Property)

The XAML structure is like:

  • MainWindow Partial Class
    • ControlTemplate GroupBox (DataContext WaterSampler instance from the list set in code)
      • DataTemplate containing button that uses bottleState control template
      • ItemsControl using DataTemplate to show lots of bottleStates
    • ControlTemplate containing the decoration of the Button used in the ItemsControl

Here's a simplified version of the code:

Items control and its data template inside the GroupBox ControlTemplate whose datacontext is an instance of WaterSampler.

<ControlTemplate x:Key="WaterSamplerGroupBoxTemplate" TargetType="{x:Type GroupBox}" >
   <GroupBox Header="{Binding Path=Header}" Width="300" Margin="10,5,10,0" HorizontalAlignment="Center">
    <StackPanel Orientation="Horizontal">
      <StackPanel.Resources>
         <DataTemplate x:Key="BottleStateDataTemplate">
               <Button Template="{DynamicResource ValveStatusTemplate}" />
         </DataTemplate>
      </StackPanel.Resources>
    <ItemsControl Name="bottleStateListBox" ItemTemplate="{StaticResource BottleStateDataTemplate}" Margin="5" Height="50" ItemsSource="{Binding BottleIsFullList}" DataContext="{Binding Parameters}"/>
    </StackPanel>
  </GroupBox>
</ControlTemplate>

The simplified button control template:

<ControlTemplate x:Key="ValveStatusTemplate" TargetType="{x:Type Button}" >
      <StackPanel Orientation="Vertical" Width="30" Margin="5" >           
           <TextBlock Text="{Binding Number}" FontSize="18" Canvas.Left="8"/>
      </StackPanel>
</ControlTemplate>

The class that holds the data for the item template:

public class DisplayBottleStateClass : INotifyPropertyChanged
{
    private int number;
    public int Number
    {
        get { return number; }
    }
}

The class containing the list of DisplayBottleClass:

public class WSParametersClass : INotifyPropertyChanged
{
    private List<DisplayBottleStateClass> bottleIsFullList = new List<DisplayBottleStateClass>();

    public List<DisplayBottleStateClass> BottleIsFullList
    {
        get { return bottleIsFullList; }
    }
}

The class containing the parameters class:

public class WaterSampler : INotifyPropertyChanged
{
    private WSParametersClass parameters = new WSParametersClass();

    public WSParametersClass Parameters
    {
        get { return parameters; }
        set { parameters = value; OnPropertyChanged("Parameters"); }
    }
}

Finally the MainWindow class:

public partial class MainWindow : Window
{
    public class WaterSamplerListClass : ObservableCollection<WaterSampler> { }
    private WaterSamplerListClass waterSamplers = new WaterSamplerListClass();
    public MainWindow()
    {
        waterSamplers.Add(new WaterSampler(0));
        WaterSampler0Group.DataContext = (waterSamplers[0]);
    }
}

I do get a binding error for the two brushes that I use but when I replace these with fixed values in the XAML still only the first element is displayed. The list also seems to update correctly through the binding as I can see the first element changing correctly. The error I get is:

System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=GradientStopHighlight; DataItem=null; target element is 'GradientStop' (HashCode=23577486); target property is 'Color' (type 'Color')

Any suggestions would be very welcome.

Thanks very much

Ed

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

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

发布评论

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

评论(2

水中月 2024-11-22 09:38:17

您的 ItemsControl 声明了 ItemsSource 和 DataContext。我相信这两个属性是互斥的 - 设置 DataContext 属性会断开控件与逻辑控件树关联的数据的连接。

删除 DataContext= 数据绑定,我想您将看到 ItemsSource 中的项目出现在 ItemsControl 中。

另请注意,ItemsControl 本身不提供任何 UI 定义。出于调试目的,放入 ListBox 或其他具体 ItemsControl 并为其提供相同的数据绑定设置以验证数据绑定是否正常可能会很有用。如果 ItemsControl 不显示任何内容,而 ListBox 却显示任何内容,那么您的问题不在于数据绑定,而在于对 ItemsControl 视觉效果进行模板化。

Your ItemsControl declares both an ItemsSource and a DataContext. I believe these two properties are mutually exclusive - setting the DataContext property disconnects the control from the data associated with the logical control tree.

Remove the DataContext= data binding and I think you'll see the items in the ItemsSource appear in your ItemsControl.

Also, note that ItemsControl doesn't provide any UI definition on its own. For debugging purposes, it can be useful to drop in a ListBox or other concrete ItemsControl and give it the same data binding settings to verify that your data bindings are sane. If the ItemsControl doesn't show anything but the ListBox does, then your problem isn't in data binding, but in templating the ItemsControl visuals.

路还长,别太狂 2024-11-22 09:38:17

尝试在 ItemsControlItemsPanelTemplate.ItemsStackPanel 上设置 CacheLength 属性。

CacheLengthMSDN

视口之外的项目的缓冲区大小(以倍数表示)
视口大小。默认值为 4.0。

备注

为了提高滚动性能,ItemsStackPanel 会为屏幕外的项目创建并缓存项目容器。
视口的两侧。 CacheLength 属性指定
屏幕外项目的缓冲区大小。您指定缓存长度
当前视口大小的倍数。例如,如果
CacheLength 为 4.0,每个视口上缓冲 2 个视口的项目
视口的一侧。可以设置较小的缓存长度来优化
启动时间,或设置更大的缓存大小以优化滚动
表现。屏幕外的项目容器是在
优先级低于视口中的优先级。

Try set the CacheLength property on the ItemsPanelTemplate.ItemsStackPanel of your ItemsControl.

CacheLength as defined by MSDN:

The size of the buffers for items outside the viewport, in multiples
of the viewport size. The default is 4.0.

Remarks

To improve scrolling performance, ItemsStackPanel creates and caches item containers for items that are off-screen on
both sides of the viewport. The CacheLength property specifies the
size of the buffers for the off-screen items. You specify CacheLength
in multiples of the current viewport size. For example, if the
CacheLength is 4.0, 2 viewports worth of items are buffered on each
side of the viewport. You can set a smaller cache length to optimize
startup time, or set a larger cache size to optimize scrolling
performance. Item containers that are off-screen are created at a
lower priority than those in the viewport.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文