我有一个带有嵌入式ComboBox的ListBox:
<ListBox ItemsSource="{Binding}">
<ListBox.ItemTemplate>
<DataTemplate>
<ComboBox Width="100" IsEditable="False" Height="20">
<TextBlock Text="Opt#1"></TextBlock>
<TextBlock Text="Opt#2"></TextBlock>
<TextBlock Text="Opt#3"></TextBlock>
</ComboBox>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
我想在未选择ListBox行时将ComboBox显示为简单文本(例如TextBlock),并在选择ListBox行时将其显示为ComboBox。
我在想,动态替换ComboBox模板就可以了。怎么做到这一点?
谢谢, 莱谢克
答案 0 :(得分:0)
交换模板的最佳方法是使用ListBox的ItemTemplateSelector属性并将其设置为您创建的继承自DataTemplateSelector的类。
以下链接提供了一个示例:http://msdn.microsoft.com/en-us/library/system.windows.controls.datatemplateselector.aspx
答案 1 :(得分:0)
只要ListBox.ItemTemplate
被选中,我就会使用一种替换ListBoxItem
的样式。
这是一个简单的例子
<ListBox.Resources>
<DataTemplate x:Key="TextBoxTemplate">
<TextBlock Text="{Binding }" />
</DataTemplate>
<DataTemplate x:Key="ComboBoxTemplate">
<ComboBox SelectedItem="{Binding }">
<ComboBoxItem>Opt#1</ComboBoxItem>
<ComboBoxItem>Opt#2</ComboBoxItem>
<ComboBoxItem>Opt#3</ComboBoxItem>
</ComboBox>
</DataTemplate>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Template" Value="{StaticResource TextBoxTemplate}" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Template" Value="{StaticResource ComboBoxTemplate}" />
</Trigger>
</Style.Triggers>
</Style>
</ListBox.Resources>
我实际上建议使用IsKeyboardFocusWithin
而不是IsSelected
作为触发器属性,因为模板可以让您与它们进行交互,而无需将项目设置为选中。
答案 2 :(得分:0)
感谢Josh和Rachel指出了我正确的方向。
我想出了一个类似于Rachel建议的解决方案。我的问题是我无法使ItemTemplateSelector工作,我不知道如何从列表框中传递状态IsSelected。我也无法使用DataTemplate,因为我的ListBox项比单个元素复杂得多(为了示例,我在上一篇文章中对其进行了简化)。
无论如何,我提出了以下解决方案。它不是很优雅,但它有效:
我在应用程序资源中定义了一种新样式:
<Style x:Key="TextBlockTemplate" TargetType="ComboBox">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<TextBlock Text="{Binding}" Margin="3" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
我将SelectionChanged和PreviewMouseDown处理程序附加到我的ListBox:
我定义了MyListBox_PreviewMouseDown:
private void MyListBox_PreviewMouseDown(object sender, MouseButtonEventArgs e) { // Grab the selected list box item. object element = (e.OriginalSource as FrameworkElement).DataContext; var item = MyListBox.ItemContainerGenerator.ContainerFromItem(element) as ListBoxItem; // Mark the row in the ListBox as selected. if (item != null) item.IsSelected = true; }
private ComboBox prevComboBox = null; private void MyListBox_SelectionChanged(object sender, SelectionChangedEventArgs e) { // Grab the list box. ListBox list = sender as ListBox; // Although there could be only one item selected, // we iterate over all selected items. foreach (MyDataItem dat in list.SelectedItems) { var item = list.ItemContainerGenerator.ContainerFromItem(dat) as ListBoxItem; // FindElement is a helper method to find an element in a visual tree. ComboBox cbo = FindElement(item, "MyComboBox") as ComboBox; if (cbo != prevComboBox) { cbo.Style = null; if (prevComboBox != null) prevComboBox.Style = (Style)Application.Current.Resources["TextBlockTemplate"]; prevComboBox = cbo; } } }
谢谢, 莱谢克