怎么让 Combobox 在展开的时候 让文本框里的内容继续显示选中项的内容而不是空白?
- 在微软网站上看到有的可以 有的不可以 如何控制?
答案
- 你好,
由于内置的控件把代码写死了:
private void OnIsDropDownOpenChanged(bool isDropDownOpen)
{
if (isDropDownOpen)
{
if (this.ElementPopup != null)
{
this.ElementPopup.IsOpen = true;
}
if (this.ElementDropDownToggle != null)
{
this.ElementDropDownToggle.IsChecked = true;
}
this.SetContentPresenter((base.SelectedItem is FrameworkElement) ? -1 : base.SelectedIndex);
this.OnDropDownOpened(EventArgs.Empty);
}
...
可以看到当DropDownOpen的时候会调用this.SetContentPresenter((base.SelectedItem is FrameworkElement) ? -1 : base.SelectedIndex);
大部分情况下SelectedItem 就是源自FrameworkElement所以等于调用了this.SetContentPresenter(-1).
再看看SetContentPresenter方法:
private void SetContentPresenter(int index)
{
...
if (index == -1)
{
if (this.ElementContentPresenter != null)
{
this.ElementContentPresenter.Content = this._emptyContent;
this.ElementContentPresenter.ContentTemplate = null;
}
this.SelectionBoxItem = null;
this.SelectionBoxItemTemplate = null;
}
...
index为-1时会把ElementContentPresenter.Content 设置为_emptyContent. ElementContentPresenter为ComboBox模板内的ContentPresenter, _emptyContent则是ComboBox模板内ContentPresenter的最初的Content:
<Border x:Name="ContentPresenterBorder">
<Grid>
<ToggleButton x:Name="DropDownToggle" HorizontalAlignment="Stretch" Margin="0" Style="{StaticResource comboToggleStyle}" VerticalAlignment="Stretch" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" HorizontalContentAlignment="Right">
<Path x:Name="BtnArrow" Stretch="Uniform" Height="4" HorizontalAlignment="Right" Margin="0,0,6,0" Width="8" Data="F1 M 301.14,-189.041L 311.57,-189.041L 306.355,-182.942L 301.14,-189.041 Z ">
<Path.Fill>
<SolidColorBrush x:Name="BtnArrowColor" Color="#FF333333"/>
</Path.Fill>
</Path>
</ToggleButton>
<ContentPresenter x:Name="ContentPresenter" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
<TextBlock/>
</ContentPresenter>
</Grid>
</Border>
解决办法就是在 this.SetContentPresenter调用之后,再次设置ContentPresenter的Content.我写了一个简单的控件,你可以参考下如何做到:
http://cid-2fa13ebc6cc8e80f.skydrive.live.com/self.aspx/Public/MyComboBox.zip
测试代码:
<c:MyComboBox Width="200" Height="50">
<ComboBoxItem Content="a"/>
<ComboBoxItem Content="b"/>
<ComboBoxItem Content="c"/>
</c:MyComboBox>
Please remember to mark the replies as answers if they help and unmark them if they provide no help. Welcome to the All-In-One Code Framework http://cfx.codeplex.com/! If you have any feedback, please tell us.- 已标记为答案zhang xiaolei 2009年11月4日 5:28
全部回复
- 你好,
由于内置的控件把代码写死了:
private void OnIsDropDownOpenChanged(bool isDropDownOpen)
{
if (isDropDownOpen)
{
if (this.ElementPopup != null)
{
this.ElementPopup.IsOpen = true;
}
if (this.ElementDropDownToggle != null)
{
this.ElementDropDownToggle.IsChecked = true;
}
this.SetContentPresenter((base.SelectedItem is FrameworkElement) ? -1 : base.SelectedIndex);
this.OnDropDownOpened(EventArgs.Empty);
}
...
可以看到当DropDownOpen的时候会调用this.SetContentPresenter((base.SelectedItem is FrameworkElement) ? -1 : base.SelectedIndex);
大部分情况下SelectedItem 就是源自FrameworkElement所以等于调用了this.SetContentPresenter(-1).
再看看SetContentPresenter方法:
private void SetContentPresenter(int index)
{
...
if (index == -1)
{
if (this.ElementContentPresenter != null)
{
this.ElementContentPresenter.Content = this._emptyContent;
this.ElementContentPresenter.ContentTemplate = null;
}
this.SelectionBoxItem = null;
this.SelectionBoxItemTemplate = null;
}
...
index为-1时会把ElementContentPresenter.Content 设置为_emptyContent. ElementContentPresenter为ComboBox模板内的ContentPresenter, _emptyContent则是ComboBox模板内ContentPresenter的最初的Content:
<Border x:Name="ContentPresenterBorder">
<Grid>
<ToggleButton x:Name="DropDownToggle" HorizontalAlignment="Stretch" Margin="0" Style="{StaticResource comboToggleStyle}" VerticalAlignment="Stretch" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" HorizontalContentAlignment="Right">
<Path x:Name="BtnArrow" Stretch="Uniform" Height="4" HorizontalAlignment="Right" Margin="0,0,6,0" Width="8" Data="F1 M 301.14,-189.041L 311.57,-189.041L 306.355,-182.942L 301.14,-189.041 Z ">
<Path.Fill>
<SolidColorBrush x:Name="BtnArrowColor" Color="#FF333333"/>
</Path.Fill>
</Path>
</ToggleButton>
<ContentPresenter x:Name="ContentPresenter" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
<TextBlock/>
</ContentPresenter>
</Grid>
</Border>
解决办法就是在 this.SetContentPresenter调用之后,再次设置ContentPresenter的Content.我写了一个简单的控件,你可以参考下如何做到:
http://cid-2fa13ebc6cc8e80f.skydrive.live.com/self.aspx/Public/MyComboBox.zip
测试代码:
<c:MyComboBox Width="200" Height="50">
<ComboBoxItem Content="a"/>
<ComboBoxItem Content="b"/>
<ComboBoxItem Content="c"/>
</c:MyComboBox>
Please remember to mark the replies as answers if they help and unmark them if they provide no help. Welcome to the All-In-One Code Framework http://cfx.codeplex.com/! If you have any feedback, please tell us.- 已标记为答案zhang xiaolei 2009年11月4日 5:28
- 辛苦了 多谢! 其实我就是想问 在不重新写控件的情况下 Combobox 本身能不能解决问题 看来是不能了.

