[英]How to get ControlTemplate not to override DataTemplate?
Similar to gmail's Select button, I wanted to create a ComboBox
for the ListView
which allows the user to quickly select entries of their choosing (ex. All, None, Read, Unread). 与gmail的“选择”按钮类似,我想为ListView
创建一个ComboBox
,它允许用户快速选择其选择的条目(例如,全部,无,已读,未读)。 However, the selected value would display a tri-state CheckBox
equivalent to All, Some, or None of the entries being selected. 但是,选定的值将显示一个三态CheckBox
相当于所有选定条目的全部,部分或无。 I succeeded in doing so. 我成功地做到了。 Below is the xaml for an example Window utilizing this feature ( * ) : 以下是使用此功能( * )的示例窗口的xaml:
<Window x:Class="WPFTest.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wpfTest="clr-namespace:WPFTest.ViewModels"
xmlns:prism="clr-namespace:Microsoft.Practices.Prism.Mvvm;assembly=Microsoft.Practices.Prism.Mvvm.Desktop"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WPFTest.Models"
mc:Ignorable="d" Title="WPF Test" Height="221.256" Width="605"
d:DataContext="{d:DesignInstance wpfTest:MainWindowViewModel, IsDesignTimeCreatable=True}"
prism:ViewModelLocator.AutoWireViewModel="True" WindowStartupLocation="CenterScreen">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary
Source="/WPFTest;Component/Resources/Resources.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
<ListView
ItemsSource="{Binding Entries}"
SelectedValue="{Binding SelectedEntry}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
ScrollViewer.CanContentScroll="True"
SelectionMode="Single"
Margin="10">
<ListView.View>
<GridView>
<GridViewColumn Width="Auto">
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox
IsChecked="{Binding Selected}"
Command="{Binding DataContext.RowSelectedCommand, RelativeSource={RelativeSource AncestorType={x:Type ListBox}}}"
HorizontalAlignment="Center"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
<GridViewColumnHeader>
<ComboBox
ItemsSource="{Binding Options.Items}"
SelectedValue="{Binding Options.SelectedItem}"
ItemTemplateSelector="{DynamicResource itemTemplateSelector}"
HorizontalAlignment="Stretch"
Margin="0,0,0,0"
VerticalAlignment="Stretch"
Width="44"
Height="34"
FontSize="20"
VerticalContentAlignment="Top"
HorizontalContentAlignment="Left">
<ComboBox.Resources>
<DataTemplate x:Key="selectedTemplate">
<TextBlock
x:Name="displayText"
Text="{Binding DataContext.Options.SelectedDisplay, RelativeSource={RelativeSource AncestorType={x:Type ListBox}}}"
FontSize="20"
Height="22"/>
</DataTemplate>
<DataTemplate x:Key="dropDownTemplate">
<TextBlock Text="{Binding}" FontSize="12"/>
</DataTemplate>
<local:ComboBoxItemTemplateSelector
x:Key="itemTemplateSelector"
SelectedTemplate="{StaticResource selectedTemplate}"
DropDownTemplate="{StaticResource dropDownTemplate}"/>
</ComboBox.Resources>
</ComboBox>
</GridViewColumnHeader>
</GridViewColumn>
<GridViewColumn
Width="Auto"
DisplayMemberBinding="{Binding Type, Mode=OneWay}"
Header="Type"/>
</GridView>
</ListView.View>
</ListView>
</Grid>
</Window>
Recently I was asked to make a style for every ComboBox
on our screens - changing their backgrounds. 最近,有人要求我为屏幕上的每个ComboBox
制作样式-更改其背景。 Because I'm on Windows8, setting the Background alone isn't enough. 因为我在Windows8上,仅设置背景是不够的。 Using this tutorial I was able to create the ControlTemplate
to get the correct behavior, with one minor error fix: 使用本教程,我能够创建ControlTemplate
以获得正确的行为,但有一个小错误修复:
<MultiTrigger.Conditions>
<Condition Property="IsGrouping" Value="True"/>
<!-- Comment out the following, it throws an error. -->
<!--<Condition>
<Condition.Value>
<sys:Boolean>False</sys:Boolean>
</Condition.Value>
</Condition>-->
</MultiTrigger.Conditions>
And usage: 和用法:
<Style
TargetType="{x:Type ComboBox}">
...
<Setter
Property="Template"
Value="{StaticResource ComboBoxStyle1}" />
</Style>
This successfully styles the ComboBox Background. 这样可以成功设置ComboBox背景的样式。 However, revisiting the former screen, I noticed that this breaks my gmail-like display. 但是,在重新访问前一个屏幕时,我注意到这会破坏我的gmail类显示。
How can I get this ControlTemplate
and the dynamic DataTemplate
to cooperate? 如何获得此ControlTemplate
和动态DataTemplate
进行协作?
( * ) ViewModels and Models can be provided if necessary for a solution. ( * )如果需要解决方案,可以提供ViewModels和Models。 Or see full working example . 或查看完整的工作示例 。
I'm not sure why you doing so complicated ComboBox
- you defined ItemTemplateSelector
twice... 我不确定为什么您要做如此复杂的ComboBox
您两次定义了ItemTemplateSelector
...
Ok - here is my 2 cents: ComboBox
is lookless control. 好的-这是我的2美分: ComboBox
是无外观控件。 It based on ControlTemplate
target type = ComboBox. 它基于ControlTemplate
目标类型= ComboBox。 Inside ComboBox
ControlTemplate
you will find ContentPresenter
. 在ComboBox
ControlTemplate
内部,您将找到ContentPresenter
。 Whatever coming into Content
of ContentPresenter
could be styled with DataTemplate
. ContentPresenter
Content
的任何Content
都可以使用DataTemplate
设置样式。 Generally - when you define DataTemplate
it wrap only ContentPresenter
or ItemsPresenter
for range based controls - not the whole ControlTemplate
obviously. 通常-当您定义DataTemplate
它仅包装 ContentPresenter
或ItemsPresenter
用于基于范围的控件-显然不是整个ControlTemplate
。
So if you want to change 'Selected' template for ComboBox
is ok but all other data should be defined via DataTemplate
for this type {x:Type local:SomeType}
that will be used by ComboBox
. 因此,如果您想更改ComboBox
“选定”模板是可以的,但所有其他数据都应通过DataTemplate
定义为ComboBox
将使用的{x:Type local:SomeType}
。
Also - consider using @galakt suggestion: use Style
with TargetType
- it easy to read, refactor, find, understand... 另外-考虑使用@galakt建议:将Style
与TargetType
一起使用-易于阅读,重构,查找,理解...
Color the Background 为背景上色
As per the OP, following this tutorial , you generate the ControlTemplate
. 按照OP,在本教程之后 ,您将生成ControlTemplate
。
To do this, you can right-click on the ComboBox element in design mode in Visual Studio 2012 or 2013 and select the “Edit template” option and then the “Edit a copy…” option. 为此,您可以在Visual Studio 2012或2013中的设计模式下右键单击ComboBox元素,然后选择“编辑模板”选项,然后选择“编辑副本...”选项。
Again note the bug fix from the OP. 再次注意OP中的错误修复。 Changing the background can then be done by: 然后可以通过以下方式更改背景:
<Border
x:Name="templateRoot"
BorderBrush="#FFACACAC"
BorderThickness="{TemplateBinding BorderThickness}"
SnapsToDevicePixels="True"
Background="{StaticResource MyComboBackgroundBrush}"> <!-- option 1 -->
<!-- <Border.Background> -->
<!-- option 2 -->
<!-- <LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="#FFF0F0F0" Offset="0"/>
<GradientStop Color="#FFE5E5E5" Offset="1"/>
</LinearGradientBrush>-->
<!-- option 3 -->
<!-- <SolidColorBrush Color="Yellow"/> -->
<!-- </Border.Background>
<Border x:Name="splitBorder" BorderBrush="Transparent" BorderThickness="1" HorizontalAlignment="Right" Margin="0" SnapsToDevicePixels="True" Width="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}">
<Path x:Name="Arrow" Data="F1M0,0L2.667,2.66665 5.3334,0 5.3334,-1.78168 2.6667,0.88501 0,-1.78168 0,0z" Fill="#FF606060" HorizontalAlignment="Center" Margin="0" VerticalAlignment="Center"/>
</Border> -->
</Border>
Interact with the DataTemplate 与DataTemplate交互
In the resource file, following the above instructions, you declared: 在资源文件中,按照上述说明进行了声明:
<ControlTemplate x:Key="ComboBoxControlTemplateBasic" TargetType="{x:Type ComboBox}"> ... <ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}" ... /> ... </ControlTemplate>
Create a copy of it with the following change, where selectedTemplate
is the key
of the DataTemplate
you want to cooperate with the ControlTemplate
: 通过以下更改创建它的副本,其中selectedTemplate
是要与ControlTemplate
合作的DataTemplate
的key
:
<ControlTemplate x:Key="ComboBoxControlTemplateHeader" TargetType="{x:Type ComboBox}"> ... <ContentPresenter x:Name="contentPresenter" ContentTemplate="{DynamicResource selectedTemplate}" ... /> ... </ControlTemplate>
Declare the appropriate styles: 声明适当的样式:
<Style TargetType="{x:Type ComboBox}"> <Setter Property="Template" Value="{StaticResource ComboBoxControlTemplateBasic}" /> <!-- other generic style setters --> </Style> <Style x:Key="ComboBoxHeader" x:Name="ComboBoxHeader" TargetType="{x:Type ComboBox}" BasedOn="{StaticResource {x:Type ComboBox}}"> <Setter Property="Template" Value="{StaticResource ComboBoxControlTemplateHeader}" /> <Setter Property="ItemTemplateSelector" Value="{DynamicResource itemTemplateSelector}"/> <!-- other specific style setters --> </Style>
Results 结果
ComboBox
shares the same look. 每个ComboBox
具有相同的外观。 DataTemplate
selectedTemplate
allows each ListView
header gmail-like ComboBox
to have the same look with unique binding values. 动态使用DataTemplate
selectedTemplate
允许每个ListView
标头类似gmail的ComboBox
具有唯一绑定值的相同外观。 Take for example the OP ComboBox
header plus the following ComboBox
with the same item source: 例如,OP ComboBox
标头以及具有相同项目源的以下ComboBox
:
<ComboBox
HorizontalAlignment="Left"
Margin="10,152,0,0"
VerticalAlignment="Top"
Width="120"
ItemsSource="{Binding Options.Items}"
SelectedValue="{Binding Options.SelectedItem}"/>
<GridViewColumnHeader>
<ComboBox
ItemsSource="{Binding Options.Items}"
SelectedValue="{Binding Options.SelectedItem}"
Style="{StaticResource ComboBoxHeader}">
<ComboBox.Resources>
<DataTemplate x:Key="selectedTemplate">
<TextBlock
x:Name="displayText"
Text="{Binding DataContext.Options.SelectedDisplay, RelativeSource={RelativeSource AncestorType={x:Type ListBox}}}"
FontSize="20"
Height="22"/>
</DataTemplate>
<DataTemplate x:Key="dropDownTemplate">
<TextBlock Text="{Binding}" FontSize="12"/>
</DataTemplate>
<local:ComboBoxItemTemplateSelector
x:Key="itemTemplateSelector"
SelectedTemplate="{StaticResource selectedTemplate}"
DropDownTemplate="{StaticResource dropDownTemplate}"/>
</ComboBox.Resources>
</ComboBox>
</GridViewColumnHeader>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.