我想验证我的项目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 …
我在一个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,它返回了正确的大小,所以它不应该绘制那个大小的边框吗?
我错过了什么?
我有一个绑定到对象集合的项控件.该对象有两个属性(名称,值),分别显示在文本块和文本框中.列表很长,我想在两列中显示它.所以我的问题是,有什么方法可以让Itemscontrol在两列中显示它的项目?
PS:该集合在运行时填充,我不知道有多少项目我必须展示!
我有一个ListBox,并希望扩展选择模式.我还想要实现拖放功能.现在的问题是,如果被点击所选项目的鼠标,它会立即被选定为单一选择,而不是等待到鼠标释放事件这样做的.
由于这种行为,开始拖动多个项目是为用户准不可能的,因为他总是点击选择要开始拖动,选择切换到与下鼠标,并与该项目开始拖拽操作的项目.
这个问题是否有一个很好的解决方法,或者甚至存在官方解决方案?
我有两个独立的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需要一起向上和向下滚动.基本上,左边的一个为右边的项目提供了各种标题.
我已经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)
但悲惨地失败了.有帮助吗?
背景: 我只知道运行时网格列和行的数量.
这是我的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)
有谁知道它是如何工作的?
我有一个(非虚拟化的)ItemsControl,它将ItemsSource绑定到ViewModel实例的ObeservableCollection.现在,一旦加载了大量的Model实例,就需要将所有ViewModel补充添加到该ObservableCollection中.如何在不使UI线程挂起的情况下添加大量ViewModel?
我想UI线程会挂起,因为每次添加新项目时,ItemsControl都需要自我更新并一遍又一遍地进行布局等.
如何处理无法虚拟化的大型动态列表?
我正在编写一个自定义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)
但我对此并不满意,我相信一定有更好的方法.任何建议,将不胜感激 !
在焦距和键盘导航方面,我看到了奇怪的行为.在下面的示例中,我有一个简化的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",那么问题就会消失.不幸的是,我在一个更大的项目中看到了这个问题,我不能仅仅删除这些焦点范围而不必担心其他与焦点相关的后果.
有人可以向我解释我所看到的奇怪行为吗?这是一个错误还是我完全错过了什么?
itemscontrol ×10
wpf ×9
xaml ×3
itemssource ×2
.net ×1
actualheight ×1
binding ×1
border ×1
c# ×1
focus ×1
itemtemplate ×1
listbox ×1
mvvm ×1
performance ×1
z-index ×1