wpf ComboBox的SelectionBoxItem相关依赖属性
以前没有注意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() 2 { 3 if (this.IsEditable) 4 { 5 this.UpdateEditableTextBox(); 6 } 7 else 8 { 9 this.UpdateSelectionBoxItem(); 10 } 11 }
1 private void UpdateSelectionBoxItem() 2 { 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) 8 { 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 } 64 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; 70 }