views:

586

answers:

2

I have a combo box that is based on a data template the includes check boxes like such:

    <ComboBox x:Name="cboComplex" Text="Select days...">
        <ComboBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <CheckBox IsChecked="{Binding Path=IsSelected}" Width="20"/>
                    <TextBlock Text="{Binding DayOfWeek}" Width="100" />
                 </StackPanel>
            </DataTemplate>

        </ComboBox.ItemTemplate>
    </ComboBox>

The problem I'm having is that I'd like the combobox to display "Select days..." and then show the list when clicked. Unfortunately setting the Text property seems to have no effect. Any ideas or help would be greatly appreciated.

Thanks in advance!

Sieg

+1  A: 

You will have to create a new Item in your underlying collection class with the value "Select Days...", with index[0] and change the selected index to 0.

    <ComboBox x:Name="cboComplex" SelectedIndex="0">
        <ComboBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <CheckBox IsChecked="{Binding Path=IsSelected}" Width="20"/>
                    <TextBlock Text="{Binding DayOfWeek}" Width="100" />
                 </StackPanel>
            </DataTemplate>

        </ComboBox.ItemTemplate>
    </ComboBox>

Or the other option is to put a label on top of it with the text "Select Days...", and then listen to OnSelectionChanged event, and if the SelectedIndex is not -1, change the labels visibility to false, otherwise true. e.g.

    private void MyListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        if (MyListBox.SelectedIndex >= 0)
        {
            MyListBoxInitialLabel.Visibility = Visibility.Hidden;
        }
        else
        {
            MyListBoxInitialLabel.Visibility = Visibility.Visible;
        }
    }
LnDCobra
+3  A: 

The Text property is used when the ComboBox is editable. You can set a default "Select" type message by adding an element to the ControlTemplate that shows up only when there is no selection and then disappears. Using this method you don't need to worry about modifying your collection or having a user try to pick the "Select" message from the list because it isn't part of the list. I'd recommend using the Tag to set your message on each instance or in a Style and then adding a new TextBlock to display it into the default template:

<TextBlock x:Name="SelectMessage" HorizontalAlignment="Left" Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Tag}" VerticalAlignment="Center" Margin="{TemplateBinding Padding}" Visibility="Collapsed"/>

Then you could use it like this:

<ComboBox ItemsSource="{Binding MyList}" Template="{StaticResource ComboBoxMessageTemplate}" Tag="Select days..."/>

Here's a complete Blend generated copy of the default Aero ComboBox template with the changes. You'll also need the theme namespace (xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero") and a reference to the PresentationFramework.Aero assembly:

<Geometry x:Key="DownArrowGeometry">M 0 0 L 3.5 4 L 7 0 Z</Geometry>
<Style x:Key="ComboBoxReadonlyToggleButton" TargetType="{x:Type ToggleButton}">
    <Setter Property="OverridesDefaultStyle" Value="true"/>
    <Setter Property="IsTabStop" Value="false"/>
    <Setter Property="Focusable" Value="false"/>
    <Setter Property="ClickMode" Value="Press"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ToggleButton}">
                <Microsoft_Windows_Themes:ButtonChrome x:Name="Chrome" SnapsToDevicePixels="true" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" RenderMouseOver="{TemplateBinding IsMouseOver}" RenderPressed="{TemplateBinding IsPressed}">
                    <Grid HorizontalAlignment="Right" Width="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}">
                        <Path x:Name="Arrow" Fill="Black" HorizontalAlignment="Center" Margin="3,1,0,0" VerticalAlignment="Center" Data="{StaticResource DownArrowGeometry}"/>
                    </Grid>
                </Microsoft_Windows_Themes:ButtonChrome>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsChecked" Value="true">
                        <Setter Property="RenderPressed" TargetName="Chrome" Value="true"/>
                    </Trigger>
                    <Trigger Property="IsEnabled" Value="false">
                        <Setter Property="Fill" TargetName="Arrow" Value="#AFAFAF"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<ControlTemplate x:Key="ComboBoxMessageTemplate" TargetType="{x:Type ComboBox}">
    <Grid x:Name="MainGrid" SnapsToDevicePixels="true">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition MinWidth="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}" Width="0"/>
        </Grid.ColumnDefinitions>
        <Popup x:Name="PART_Popup" Margin="1" AllowsTransparency="true" IsOpen="{Binding IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}}" Placement="Bottom" PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}" Grid.ColumnSpan="2">
            <Microsoft_Windows_Themes:SystemDropShadowChrome x:Name="Shdw" MaxHeight="{TemplateBinding MaxDropDownHeight}" MinWidth="{Binding ActualWidth, ElementName=MainGrid}" Color="Transparent">
                <Border x:Name="DropDownBorder" Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}" BorderBrush="{DynamicResource {x:Static SystemColors.WindowFrameBrushKey}}" BorderThickness="1">
                    <ScrollViewer CanContentScroll="true">
                        <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" KeyboardNavigation.DirectionalNavigation="Contained"/>
                    </ScrollViewer>
                </Border>
            </Microsoft_Windows_Themes:SystemDropShadowChrome>
        </Popup>
        <ToggleButton Style="{StaticResource ComboBoxReadonlyToggleButton}" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" Grid.ColumnSpan="2" IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"/>
        <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" IsHitTestVisible="false" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" Content="{TemplateBinding SelectionBoxItem}" ContentStringFormat="{TemplateBinding SelectionBoxItemStringFormat}" ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}" ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"/>
        <TextBlock x:Name="SelectMessage" HorizontalAlignment="Left" Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Tag}" VerticalAlignment="Center" Margin="{TemplateBinding Padding}" Visibility="Collapsed"/>
    </Grid>
    <ControlTemplate.Triggers>
        <Trigger Property="SelectedItem" Value="{x:Null}">
            <Setter Property="Visibility" TargetName="SelectMessage" Value="Visible"/>
        </Trigger>
        <Trigger Property="HasDropShadow" SourceName="PART_Popup" Value="true">
            <Setter Property="Margin" TargetName="Shdw" Value="0,0,5,5"/>
            <Setter Property="Color" TargetName="Shdw" Value="#71000000"/>
        </Trigger>
        <Trigger Property="HasItems" Value="false">
            <Setter Property="Height" TargetName="DropDownBorder" Value="95"/>
        </Trigger>
        <Trigger Property="IsEnabled" Value="false">
            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
            <Setter Property="Background" Value="#FFF4F4F4"/>
        </Trigger>
        <Trigger Property="IsGrouping" Value="true">
            <Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>
John Bowen
+1 Thanks, good answer. Just one extra thing to add to the TextBlock is HitTestVisible="False".
Jon Mitchell