First, preface
Take a look at WPF's own ComboBox in a non-editable state, with custom ItemTemplate, as shown in the results:
Its currently selected item (within the red box) is the same as the custom ItemTemplate;
But C1combobox's non-editable state (iseditable= "False"):
Always feel that its non-editing status is not completed, although the numbers and English can not be entered, but in the red box will still be able to input Chinese text (QQ Pinyin Input method of Chinese input state); and in the non-editable state is not like the Combobox's non-editable state can display the custom ItemTemplate effect This article describes how to use C1combobox to mimic the non-editing state effect of a ComboBox.
Second, the solution
First analyze the control structure of the C1combobox:
Where the Comboheader part is displayed by switching back and forth from two controls,
Internal C1textboxbase _elementeditcontrol; Internal ContentPresenter _elementcontentcontrol;
_elementeditcontrol is the control that is displayed in the edit state, _elementcontentcontrol the control that is displayed in the non-editable state (the custom ItemTemplate can be displayed);
The two control transformations display the following methods (C1texteditablecontentcontrol):
1 protected Internal voidUpdatevisualstate ()2{3 if( This. Editcontrol = =NULL|| This. ContentControl = =NULL)4{5 return;6}7 if( This. Isineditmode | | This. Isdropdownopen)8{9 This. Editcontrol.opacity = 1.0;Ten This. Editcontrol.istabstop =true; One This. Editcontrol.ishittestvisible =true; A This. contentcontrol.visibility = visibility.collapsed; - This. Contentcontrol.content =NULL; -} the Else -{ - This. editcontrol.opacity = 1.4012984643248171E-45; - This. Editcontrol.istabstop =false; + This. Editcontrol.ishittestvisible =false; - This. contentcontrol.visibility = visibility.visible; + This. Contentcontrol.content = This. Actualcontent; A} at Base. Cursor = ( This. Iseditable? Cursors.IBeam:Cursors.Arrow); -} - //Note: Editcontrol corresponds to _elementeditcontrol,contentcontrol corresponding to _elementcontentcontrol;
That is, when this. Isineditmode | | this. When Isdropdownopen is false, the custom Itemplate can be displayed;
Therefore, when the ScrollViewer shrinks (Isdropdownopen is false), the isineditmode of the Comboheader is set to false to ensure that the drop-down option is displayed in Comboheader after the custom itemt Emplate;
Loaded + = (sender, e) =>{ typeof(C1texteditablecontentcontrol)) [0]; Cmb. Isdropdownopenchanged + = (sender2, e2) = { false; };};
1 PublicList<t> getchildobjects<t> (DependencyObject obj, Type TypeName) where t:frameworkelement2{3DependencyObject Child =NULL;4List<t> childlist =NewList<t> ();5 6 for(inti = 0; I <= visualtreehelper.getchildrencount (obj)-1; i++)7{8Child = Visualtreehelper.getchild (obj, i);9 Ten if(Child isT && ((T) child). GetType () = = typename)) One{ AChildlist.add ((T) child); -} -Childlist.addrange (getchildobjects<t> (Child, TypeName)); the} - returnChildlist; -}
Getchildobjects Method
However, when Comboheader gets the focus, the Editcontrol is still displayed instead of ContentControl, so add the following code:
false; Editbox.gotfocus + = (sender2, E2) =>{ false;};
It is important to note that if editbox.iseditable = falseis not set; , click two times Comboheader or will enter the editing state, show Editcontrol ...
Continue however, when you click the Arrowtoggle button to expand the ScrollViewer, will still show the editing state, this is troublesome, check the source, the operation will trigger the Updateswappedout method to modify the _elementcomboheader Actualcontent, which in turn triggers the Updatevisualstate method above, at which point the Isdropdownopen property of ScrollViewer is true, resulting in the display of the editing state, not the custom ItemTemplate;
1 Private voidUpdateswappedout ()2{3 if( This. _elementcomboheader = =NULL)4{5 return;6}7 This. _elementcomboheader.isdropdownopen = This. Isdropdownopen;8C1comboboxitem C1comboboxitem =NULL;9 This. _isheaderupdate =true;Ten This. _elementcomboheader.actualcontent =NULL; One This. _isheaderupdate =false; A This. _elementcomboheader.updateiswatermarked (); - This. _elementcomboheader.updatevisualstate (); - if( This. Swappedoutitem! =NULL) the{ - This. Swappedoutitem.swappedout =false; - This. Swappedoutitem =NULL; -} + if( This. SelectedItem = =NULL) -{ + return; A} at if( This. SelectedIndex! =-1) -{ -C1comboboxitem = (C1comboboxitem)Base. Itemcontainergenerator.containerfromindex ( This. SelectedIndex); - if(C1comboboxitem! =NULL&&! This. Isdropdownopen) -{ - This. Swappedoutitem = C1comboboxitem; inC1comboboxitem.swappedout =true; -} to} + if(C1comboboxitem = =NULL) -{ theC1comboboxitem = ( This. SelectedItem asC1comboboxitem); *} $ This. _isheaderupdate =true;Panax Notoginseng if(C1comboboxitem = =NULL) -{ the if(Base. Itemstringformat! =NULL&&! This. Iseditable &&Base. ItemTemplate = =NULL) +{ A This. _elementcomboheader.actualcontent = This. Formattedstring (Base. Itemstringformat, This. SelectedItem); the} + Else -{ $ This. _elementcomboheader.actualcontent = This. SelectedItem; $} -} - Else if(Base. Itemstringformat! =NULL&&! This. Iseditable &&Base. ItemTemplate = =NULL) the{ - This. _elementcomboheader.actualcontent = This. Formattedstring (Base. Itemstringformat, c1comboboxitem.content);Wuyi} the Else -{ Wu This. _elementcomboheader.actualcontent = c1comboboxitem.content; -} About This. _isheaderupdate =false; $ This. _elementcomboheader.isdirty =false; -}
View Code
I can't find it. How to disable triggering of the Updateswappedout method, or how to set Isdropdownopen to false after triggering, so take Editcontrol and ContentControl two controls out, and then write a Updatevisualstate to update the conversion of two States;
1 Private voidUpdatevisualstate ()2{3 if( This. Editcontrol = =NULL|| This. ContentControl = =NULL)4{5 return;6}7 This. editcontrol.opacity = 1.4012984643248171E-45;8 This. Editcontrol.istabstop =false;9 This. Editcontrol.ishittestvisible =false;Ten This. contentcontrol.visibility = visibility.visible; OneC1comboboxitem Cmbi = ((C1comboboxitem) CMB. Itemcontainergenerator.containerfromindex (CMB. SelectedIndex)); A This. Contentcontrol.content = Cmbi. Content; - Base. Cursor = (editbox.iseditable? Cursors.IBeam:Cursors.Arrow); -}
1 editcontrol = getchildobjects<control> (CMB, "editcontrol") [0]; 2 ContentControl = getchildobjects<contentpresenter> (CMB, "ContentControl") [0]; 3 CMB. Isdropdownopenchanged + = (sender2, e2) = 4 { 5 //Editbox.isineditmode = false; 6 Updatevisualstate (); 7 };
1 PublicList<t> getchildobjects<t> (DependencyObject obj,stringName) where t:frameworkelement2{3DependencyObject Child =NULL;4List<t> childlist =NewList<t> ();5 6 for(inti = 0; I <= visualtreehelper.getchildrencount (obj)-1; i++)7{8Child = Visualtreehelper.getchild (obj, i);9 Ten if(Child isT && ((T) child). Name = = Name |string. IsNullOrEmpty (name))) One{ AChildlist.add ((T) child); -} -Childlist.addrange (getchildobjects<t> (Child, name)); the} - returnChildlist; -}
All over, the effect is as follows:
Initial state:
Expand Status:
Select the post-change state:
Third, Resources download
1, demo project download: http://files.cnblogs.com/files/memento/C1ComboBoxSample.7z
[WPF] Non-editable state of C1combobox