标签: itemscontrol

强制WPF在ItemsControl中创建项目

我想验证我的项目ListBox是否在UI中正确显示.我认为这样做的一种方法是遍历ListBox视觉树中的所有孩子,获取他们的文本,然后将其与我期望的文本进行比较.

这种方法的问题是内部ListBox使用a VirtualizingStackPanel来显示其项目,因此只创建可见的项目.我最终遇到了这个ItemContainerGenerator类,它看起来应该强制WPF在可视树中为指定项创建控件.不幸的是,这对我造成了一些奇怪的副作用.这是我生成以下所有项目的代码ListBox:

List<string> generatedItems = new List<string>();
IItemContainerGenerator generator = this.ItemsListBox.ItemContainerGenerator;
GeneratorPosition pos = generator.GeneratorPositionFromIndex(-1);
using(generator.StartAt(pos, GeneratorDirection.Forward))
{
    bool isNewlyRealized;
    for(int i = 0; i < this.ItemsListBox.Items.Count; i++)
    {
        isNewlyRealized = false;
        DependencyObject cntr = generator.GenerateNext(out isNewlyRealized);
        if(isNewlyRealized)
        {
            generator.PrepareItemContainer(cntr);
        }

        string itemText = GetControlText(cntr);
        generatedItems.Add(itemText);
    }
}
Run Code Online (Sandbox Code Playgroud)

(GetItemText()如果你愿意,我可以提供代码,但它只是遍历可视树,直到TextBlock找到它.我意识到还有其他方法可以在项目中包含文本,但是一旦我得到项目,我会解决这个问题一代人正常工作.)

在我的应用程序中,ItemsListBox包含20个项目,最初的12个项目最初可见.前14项的文本是正确的(可能是因为它们的控件已经生成).但是,对于第15-20项,我根本没有任何文字.另外,如果我滚动到底部ItemsListBox,项目15-20的文本也是空白的.因此,我似乎正在干扰WPF生成控件的常规机制.

我究竟做错了什么?是否有一种不同/更好的方法可以强制将项ItemsControl添加到可视树中?

更新:我认为我已经找到了为什么会发生这种情况,虽然我不知道如何解决它.我假设调用PrepareItemContainer()将生成任何必要的控件来显示项目,然后将容器添加到可视树中的正确位置.事实证明,它没有做这两件事.容器没有被添加到ItemsControl直到我向下滚动才能查看它,并且在那时只ListBoxItem …

wpf itemscontrol

6
推荐指数
1
解决办法
7800
查看次数

如何在ItemsControl周围放置边框?

我在一个usercontrol中有一个带有自定义面板的itemscontrol.usercontrols大小仅受父窗口大小的约束.

<UserControl>
  <Grid>
    <Border BorderBrush="DarkGray" BorderThickness="5">
      <ItemsControl ItemsSource="{Binding ActiveGame.Grid.CellsFlat}">
        <ItemsControl.ItemsPanel>
          <ItemsPanelTemplate>
            <Wpf:HexagonalPanel/>
          </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
          <DataTemplate>
            <Button />
          </DataTemplate>
        </ItemsControl.ItemTemplate>
      </ItemsControl>
    </Border>
  </Grid>
</UserControl>
Run Code Online (Sandbox Code Playgroud)

我现在想要仅在生成的面板周围绘制边框.但相反,它是围绕整个网格绘制的,或者可能更精确地与网格大小相同.

我想我在HexagonalPanel上正确实现了MeasureOverride,它返回了正确的大小,所以它不应该绘制那个大小的边框吗?

我错过了什么?

wpf xaml border itemscontrol

6
推荐指数
2
解决办法
1万
查看次数

在两列(WPF)中显示itemscontrol中的项目

我有一个绑定到对象集合的项控件.该对象有两个属性(名称,值),分别显示在文本块和文本框中.列表很长,我想在两列中显示它.所以我的问题是,有什么方法可以让Itemscontrol在两列中显示它的项目?

PS:该集合在运行时填充,我不知道有多少项目我必须展示!

.net wpf itemscontrol

6
推荐指数
2
解决办法
8582
查看次数

WPF从具有SelectionMode = Extended的ListBox拖放

我有一个ListBox,并希望扩展选择模式.我还想要实现拖放功能.现在的问题是,如果被点击所选项目的鼠标,它会立即被选定为单一选择,而不是等待到鼠标释放事件这样做的.

由于这种行为,开始拖动多个项目是为用户准不可能的,因为他总是点击选择要开始拖动,选择切换到与下鼠标,并与该项目开始拖拽操作的项目.

这个问题是否有一个很好的解决方法,或者甚至存在官方解决方案?

wpf drag-and-drop listbox itemscontrol

6
推荐指数
1
解决办法
4655
查看次数

绑定到Item ItemsControl的ActualHeight

我有两个独立的ItemsControls并排出现.在ItemsControl小号绑定到相同的ItemsSource,但他们不同的方式显示数据.

左侧显示的每个项目很可能小于右侧的相同项目.这会导致问题,因为行不会排成一行,因此我需要左侧的项目绑定到右侧的项目.

ItemsControl        ItemsControl
|Item 1         |Item 1
|Item 2         |Item 2
|Item 3         |
|Item 4         |Item 3
Run Code Online (Sandbox Code Playgroud)

如您所见,右侧的第2项更大,因此它会抛弃对齐.因此,如果我可以将左侧的项目2绑定到右侧的项目2,ActualHeight则问题将得到解决.我怎样才能在XAML中做到这一点?

编辑:为了使事情变得更复杂,ItemsControl右边需要从右向左滚动,但两者都ItemsControls需要一起向上和向下滚动.基本上,左边的一个为右边的项目提供了各种标题.

wpf xaml binding itemscontrol actualheight

6
推荐指数
1
解决办法
4835
查看次数

如何在后面的代码中将ItemsPanelTemplate设置为动态创建的Grid

我已经UserControl定义了这个XAML并且想ItemsPanelTemplate在我的代码后面动态设置(XAML在示例中不是这样):

<UserControl>
    <ItemsControl x:Name="Items">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Grid> <!-- I want to add this Grid definition in code behind -->
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition />
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                        <RowDefinition />
                    </Grid.RowDefinitions>
                </Grid>
            </ItemsPanelTemplate>
       </ItemsControl.ItemsPanel>
    </ItemsControl>
</UserControl>
Run Code Online (Sandbox Code Playgroud)

我试过类似的东西

this.Items.ItemsPanel.Template = new Grid();
Run Code Online (Sandbox Code Playgroud)

但悲惨地失败了.有帮助吗?

背景: 我只知道运行时网格列和行的数量.

c# wpf xaml itemscontrol itemspaneltemplate

6
推荐指数
2
解决办法
8258
查看次数

修改ItemsControl中项目的ZIndex

这是我的ItemsControl的代码,当鼠标移过时放大项目.
我没有设法增加当前缩放项目的ZIndex以将其放在其他项目上.

<ItemsControl ItemsSource="{Binding Path=Value}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Path=Name}"
                       RenderTransformOrigin="0.5 0.5">
                <TextBlock.Style>
                    <Style TargetType="{x:Type TextBlock}">
                        <Style.Triggers>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter Property="RenderTransform">
                                    <Setter.Value>
                                        <ScaleTransform ScaleX="1.5"
                                                        ScaleY="1.5" />
                                    </Setter.Value>
                                </Setter>
                            </Trigger>
                        </Style.Triggers>
                    </Style>
                </TextBlock.Style>
            </TextBlock>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
    <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <WrapPanel Orientation="Horizontal" />
            </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
Run Code Online (Sandbox Code Playgroud)

我试图在触发器中直接更改ZIndex,但它不起作用.
我似乎需要更改ContentPresenter中的ZIndex,它是VisualTree中TextBlock的Parent,而不是直接在TextBlock中.

<Setter Property="Panel.ZIndex" Value="99" />
Run Code Online (Sandbox Code Playgroud)

所以我尝试在ContentPresenter中更改ZIndex,但它仍然不起作用

<ItemsControl.ItemContainerStyle>
    <Style TargetType="{x:Type ContentPresenter}">
        <Style.Triggers>
            <Trigger Property="IsMouseOver" Value="True">
                <Setter Property="Panel.ZIndex" Value="99" />
            </Trigger>
        </Style.Triggers>
    </Style>
</ItemsControl.ItemContainerStyle>
Run Code Online (Sandbox Code Playgroud)

有谁知道它是如何工作的?

wpf z-index itemscontrol rendertransform

6
推荐指数
1
解决办法
6804
查看次数

ItemsControl.ItemsSource MVVM性能

我有一个(非虚拟化的)ItemsControl,它将ItemsSource绑定到ViewModel实例的ObeservableCollection.现在,一旦加载了大量的Model实例,就需要将所有ViewModel补充添加到该ObservableCollection中.如何在不使UI线程挂起的情况下添加大量ViewModel?

我想UI线程会挂起,因为每次添加新项目时,ItemsControl都需要自我更新并一遍又一遍地进行布局等.

  • 我应该暂停绑定添加所有项目,然后恢复?如果是这样,怎么样?
  • 我应该覆盖ObservableCollection以实现AddRange,因此只添加1个CollectionChanged事件来添加多个项目吗?或者只是替换整个系列?
  • 或者分别添加每个项目并分别为每个项目调用Dispatcher.Invoke更好?所以我会经常解锁.

如何处理无法虚拟化的大型动态列表?

performance itemscontrol mvvm itemssource

5
推荐指数
1
解决办法
3759
查看次数

WPF - 从ItemsSource中删除项目的最佳方法

我正在编写一个自定义ItemsControl(标签式文档容器),当用户关闭它时,每个项目(选项卡)都可以从UI中删除.但是,我不能直接从ItemsControl.Items集合中删除它,因为这些项可以是数据绑定.所以,我必须从删除它ItemsSource,它可以是任何东西(ICollection,DataTable,DataSourceProvider...).

在我的应用程序的上下文中,我知道它的实际类型是什么ItemsSource,但我希望该控件更通用,以便我可以在以后重用它.

所以我正在寻找一种从数据源中删除项目的方法,而不知道它的类型.我可以使用反射,但感觉很脏......到目前为止,我想出的最佳解决方案是使用dynamic:

    internal void CloseTab(TabDocumentContainerItem tabDocumentContainerItem)
    {
        // TODO prompt user for confirmation (CancelEventHandler ?)

        var item = ItemContainerGenerator.ItemFromContainer(tabDocumentContainerItem);

        // TODO find a better way...
        try
        {
            dynamic items = ItemsSource;
            dynamic it = item;
            items.Remove(it);
        }
        catch(RuntimeBinderException ex)
        {
            Trace.TraceError("Oops... " + ex.ToString());
        }
    }
Run Code Online (Sandbox Code Playgroud)

但我对此并不满意,我相信一定有更好的方法.任何建议,将不胜感激 !

wpf itemscontrol itemssource

5
推荐指数
2
解决办法
2万
查看次数

简单的WPF ItemsControl的焦点行为

在焦距和键盘导航方面,我看到了奇怪的行为.在下面的示例中,我有一个简化的ItemsControl,它已经模板化,因此它显示了一个绑定到ItemsSource的CheckBoxes列表.

<ItemsControl FocusManager.IsFocusScope="True"
              ItemsSource="{Binding ElementName=TheWindow, Path=ListOStrings}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <CheckBox Content="{Binding}" />
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>
Run Code Online (Sandbox Code Playgroud)

由于某些奇怪的原因,FocusManager.IsFocusScope ="True"分配导致在通过鼠标单击选中复选框时无法设置键盘焦点,并且当使用空格键选中复选框时,焦点将跳出ItemsControl.键盘.这两个症状似乎都指向选中复选框时发生的一些奇怪的导航,但我很难找到它的底部.

如果我使用此方法将可视树中的任何父元素设置为焦点范围,则会出现此问题.如果我删除了FocusManager.IsFocusScope ="True",那么问题就会消失.不幸的是,我在一个更大的项目中看到了这个问题,我不能仅仅删除这些焦点范围而不必担心其他与焦点相关的后果.

有人可以向我解释我所看到的奇怪行为吗?这是一个错误还是我完全错过了什么?

wpf focus itemtemplate itemscontrol keyboard-navigation

5
推荐指数
2
解决办法
6909
查看次数