WPF:根据列表框项目大小动态更改列表框的项目模板
我需要根据列表框项目计数更改列表框的数据模板。我提出了以下 XAML:
<Window.Resources>
<DataTemplate x:Key="DefaultTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=Text}"/>
<TextBlock Text="default template" />
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="OtherTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=Text}"/>
<TextBlock Text="other template" />
</StackPanel>
</DataTemplate>
</Window.Resources>
<ListBox Name="listBox1" ItemsSource="{Binding Path=Items}">
<ListBox.Style>
<Style TargetType="{x:Type ListBox}">
<Setter Property="ItemTemplate" Value="{StaticResource DefaultTemplate}" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Items.Count}" Value="1">
<Setter Property="ItemTemplate" Value="{StaticResource OtherTemplate}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ListBox.Style>
</ListBox>
使用上述 XAML,一旦我将两个或多个项目添加到绑定列表中,数据模板就会按预期更改(从其他更改为默认)。但是,如果我删除列表中包含两个以上项目的第一个项目,则整个列表框将变为空(我验证了绑定列表非空)。不过,删除两个项目列表中的第二个项目效果很好(即模板从默认更改为其他)。
有什么想法为什么会发生这种情况吗?或者也许我解决这个问题的方法是错误的?
I need to change the DataTemplate of my ListBox, based on the ListBox items count. I have come up with the following XAML:
<Window.Resources>
<DataTemplate x:Key="DefaultTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=Text}"/>
<TextBlock Text="default template" />
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="OtherTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=Text}"/>
<TextBlock Text="other template" />
</StackPanel>
</DataTemplate>
</Window.Resources>
<ListBox Name="listBox1" ItemsSource="{Binding Path=Items}">
<ListBox.Style>
<Style TargetType="{x:Type ListBox}">
<Setter Property="ItemTemplate" Value="{StaticResource DefaultTemplate}" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Items.Count}" Value="1">
<Setter Property="ItemTemplate" Value="{StaticResource OtherTemplate}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ListBox.Style>
</ListBox>
With the above XAML, once I added two or more items to the bound list, the data template changed as expected (from other to default). However, if I remove the first item in the list with more than two items, the entire listbox just becomes empty (I verified that the bound list is non-empty). Removing the second item in a two items list works fine though (i.e. template changed from default to other).
Any ideas why this is happening? Or perhaps I went about the wrong way to solve this problem?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可以使用数据触发器,也可以使用
DataTemplateSelector
这里是一篇介绍基础知识的文章。 这里是 MSDN将其应用于项目控件(也是列表框)you could use data triggers, or you could use a
DataTemplateSelector
Here is an article that shows the basics. and here is the MSDN on applying it to the items control (also, a listbox)我无法说出确切的问题或原因,但这是因为 DataTrigger 在计数为 1 并且只有 1 时设置模板。
您可以执行 3 件事中的 1 件事来解决此问题,但我建议只做 1 件事。
a) 通过派生自 System.Windows.TriggerBase< 来实现您自己的 DataTrigger /a>
b) 使用 System.Windows 的实现。 Data.IValueConverter 将从 ItemsControl.Items.Count 转换为 DataTemplate。通过将元素作为 Binding.ConverterParameter 放置在资源范围内,将其转换为 FrameWorkElement 并调用 FrameWorkElement.FindResource() 来检索模板。
C)这是我的建议,编写您自己的 DataTemplateSelector 做繁重的工作。该机制专门针对您所实现的功能。我最近编写了一个,它将根据源对象的类型选择 DataTemplate,而不需要没有设置 x:Key 的 DataTemplate。使用模板选择器上的属性,您可以使用 XAML 将 DataTemplates 传递到 DataTemplateSelector,从而删除 FindResource 代码“待办事项”列表。
I can't speak for the exact problem or the cause, but it is because a DataTrigger is setting a template when the count is 1 and only 1.
You can do 1 of 3 things to solve this problem, but only 1 I would recommend.
a) Implement your own DataTrigger by deriving from System.Windows.TriggerBase
b) Use an implementation of System.Windows.Data.IValueConverter that will convert from ItemsControl.Items.Count into a DataTemplate. Retrieve the templates by placing an element in scope of your resources as Binding.ConverterParameter, casting them to FrameWorkElement and call FrameWorkElement.FindResource().
C) This is my recommendation, write your own DataTemplateSelector to do the grunt work. This mechanism is specifically targeted at the functionality you with you achieve. I recently wrote one that will pick a DataTemplate based on the type of the source object without requiring a DataTemplate with no x:Key set. Using Properties on the template selector, you can pass DataTemplates into the DataTemplateSelector using XAML, removing that FindResource code 'todo' list.