以前没有注意SelectionBoxItem相关依赖属性,这几天看wpf源码 特意研究了一番
1 <Style x:Key="ComboBoxStyle1" TargetType="{x:Type ComboBox}">
2 <Setter Property="FocusVisualStyle" Value="{StaticResource ComboBoxFocusVisual}"/>
3 <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}"/>
4 <Setter Property="Background" Value="{StaticResource ButtonNormalBackground}"/>
5 <Setter Property="BorderBrush" Value="{StaticResource ButtonNormalBorder}"/>
6 <Setter Property="BorderThickness" Value="1"/>
7 <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
8 <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
9 <Setter Property="Padding" Value="4,3"/>
10 <Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
11 <Setter Property="ScrollViewer.PanningMode" Value="Both"/>
12 <Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
13 <Setter Property="Template">
14 <Setter.Value>
15 <ControlTemplate TargetType="{x:Type ComboBox}">
16 <Grid x:Name="MainGrid" SnapsToDevicePixels="true">
17 <Grid.ColumnDefinitions>
18 <ColumnDefinition Width="*"/>
19 <ColumnDefinition MinWidth="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}" Width="0"/>
20 </Grid.ColumnDefinitions>
21 <Popup x:Name="PART_Popup" AllowsTransparency="true" Grid.ColumnSpan="2" IsOpen="{Binding IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}}" Margin="1" PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}" Placement="Bottom">
22 <Microsoft_Windows_Themes:SystemDropShadowChrome x:Name="Shdw" Color="Transparent" MaxHeight="{TemplateBinding MaxDropDownHeight}" MinWidth="{Binding ActualWidth, ElementName=MainGrid}">
23 <Border x:Name="DropDownBorder" BorderBrush="{DynamicResource {x:Static SystemColors.WindowFrameBrushKey}}" BorderThickness="1" Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}">
24 <ScrollViewer x:Name="DropDownScrollViewer">
25 <Grid RenderOptions.ClearTypeHint="Enabled">
26 <Canvas HorizontalAlignment="Left" Height="0" VerticalAlignment="Top" Width="0">
27 <Rectangle x:Name="OpaqueRect" Fill="{Binding Background, ElementName=DropDownBorder}" Height="{Binding ActualHeight, ElementName=DropDownBorder}" Width="{Binding ActualWidth, ElementName=DropDownBorder}"/>
28 </Canvas>
29 <ItemsPresenter x:Name="ItemsPresenter" KeyboardNavigation.DirectionalNavigation="Contained" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
30 </Grid>
31 </ScrollViewer>
32 </Border>
33 </Microsoft_Windows_Themes:SystemDropShadowChrome>
34 </Popup>
35 <ToggleButton BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" Grid.ColumnSpan="2" IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Style="{StaticResource ComboBoxReadonlyToggleButton}"/>
36 <ContentPresenter ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}" ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}" Content="{TemplateBinding SelectionBoxItem}" ContentStringFormat="{TemplateBinding SelectionBoxItemStringFormat}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" IsHitTestVisible="false" Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
37 </Grid>
38 <ControlTemplate.Triggers>
39 <Trigger Property="HasDropShadow" SourceName="PART_Popup" Value="true">
40 <Setter Property="Margin" TargetName="Shdw" Value="0,0,5,5"/>
41 <Setter Property="Color" TargetName="Shdw" Value="#71000000"/>
42 </Trigger>
43 <Trigger Property="HasItems" Value="false">
44 <Setter Property="Height" TargetName="DropDownBorder" Value="95"/>
45 </Trigger>
46 <Trigger Property="IsEnabled" Value="false">
47 <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
48 <Setter Property="Background" Value="#FFF4F4F4"/>
49 </Trigger>
50 <Trigger Property="IsGrouping" Value="true">
51 <Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
52 </Trigger>
53 <Trigger Property="ScrollViewer.CanContentScroll" SourceName="DropDownScrollViewer" Value="false">
54 <Setter Property="Canvas.Top" TargetName="OpaqueRect" Value="{Binding VerticalOffset, ElementName=DropDownScrollViewer}"/>
55 <Setter Property="Canvas.Left" TargetName="OpaqueRect" Value="{Binding HorizontalOffset, ElementName=DropDownScrollViewer}"/>
56 </Trigger>
57 </ControlTemplate.Triggers>
58 </ControlTemplate>
59 </Setter.Value>
60 </Setter>
61 <Style.Triggers>
62 <Trigger Property="IsEditable" Value="true">
63 <Setter Property="BorderBrush" Value="{StaticResource TextBoxBorder}"/>
64 <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
65 <Setter Property="IsTabStop" Value="false"/>
66 <Setter Property="Padding" Value="3"/>
67 <Setter Property="Template" Value="{StaticResource ComboBoxEditableTemplate}"/>
68 </Trigger>
69 </Style.Triggers>
70 </Style>
可以看到在文本模式下 ContentPresenter 相关依赖属性 ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}" ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}" Content="{TemplateBinding SelectionBoxItem}" ContentStringFormat="{TemplateBinding SelectionBoxItemStringFormat}"是通过这几个SelectionBoxItem属性绑定的
以下为ComboBox相关源码
通过获取InternalSelectedItem为ComboBoxItem的content,contentTemplete,contentStringFormat属性传递给
internalSelectedItem
,
itemTemplate ,
itemStringFormat
1 private void Update()
3 if (this.IsEditable)
5 this.UpdateEditableTextBox();
7 else
9 this.UpdateSelectionBoxItem();
10 }
1 private void UpdateSelectionBoxItem()
3 object internalSelectedItem = base.InternalSelectedItem;
4 DataTemplate itemTemplate = base.ItemTemplate;
5 string itemStringFormat = base.ItemStringFormat;
6 ContentControl control = internalSelectedItem as ContentControl;
7 if (control != null)
9 internalSelectedItem = control.Content;
10 itemTemplate = control.ContentTemplate;
11 itemStringFormat = control.ContentStringFormat;
12 }
13 if (this._clonedElement != null)
14 {
15 this._clonedElement.LayoutUpdated -= new EventHandler(this.CloneLayoutUpdated);
16 this._clonedElement = null;
17 }
18 if (((itemTemplate == null) && (base.ItemTemplateSelector == null)) && (itemStringFormat == null))
19 {
20 DependencyObject d = internalSelectedItem as DependencyObject;
21 if (d != null)
22 {
23 this._clonedElement = d as UIElement;
24 if (this._clonedElement != null)
25 {
26 VisualBrush brush = new VisualBrush(this._clonedElement) {
27 Stretch = Stretch.None,
28 ViewboxUnits = BrushMappingMode.Absolute,
29 Viewbox = new Rect(this._clonedElement.RenderSize),
30 ViewportUnits = BrushMappingMode.Absolute,
31 Viewport = new Rect(this._clonedElement.RenderSize)
32 };
33 DependencyObject parent = VisualTreeHelper.GetParent(this._clonedElement);
34 FlowDirection direction = (parent == null) ? FlowDirection.LeftToRight : ((FlowDirection) parent.GetValue(FrameworkElement.FlowDirectionProperty));
35 if (base.FlowDirection != direction)
36 {
37 brush.Transform = new MatrixTransform(new Matrix(-1.0, 0.0, 0.0, 1.0, this._clonedElement.RenderSize.Width, 0.0));
38 }
39 Rectangle rectangle = new Rectangle {
40 Fill = brush,
41 Width = this._clonedElement.RenderSize.Width,
42 Height = this._clonedElement.RenderSize.Height
43 };
44 this._clonedElement.LayoutUpdated += new EventHandler(this.CloneLayoutUpdated);
45 internalSelectedItem = rectangle;
46 itemTemplate = null;
47 }
48 else
49 {
50 internalSelectedItem = ExtractString(d);
51 itemTemplate = ContentPresenter.StringContentTemplate;
52 }
53 }
54 }
55 if (internalSelectedItem == null)
56 {
57 internalSelectedItem = string.Empty;
58 itemTemplate = ContentPresenter.StringContentTemplate;
59 }
60 this.SelectionBoxItem = internalSelectedItem;
61 this.SelectionBoxItemTemplate = itemTemplate;
62 this.SelectionBoxItemStringFormat = itemStringFormat;
63 }
65 private void UpdateTextBox(string matchedText, string newText)
66 {
67 this.EditableTextBoxSite.Text = matchedText;
68 this.EditableTextBoxSite.SelectionStart = newText.Length;
69 this.EditableTextBoxSite.SelectionLength = matchedText.Length - newText.Length;