ComboBox with fixed Header - c#

I need to show a default text in my ComboBox, this text must not changed also when the user select an item of the Combobox, actually for do this I've created this structure:
<ComboBox ItemsSource="{Binding AvailableNations}" Width="160" Height="55" Margin="0, 0, 0, 15"
Text="Select Countries" IsEditable="True">
<ComboBox.ItemTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding IsChecked}" Content="{Binding Item.Name}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
this display as default text Select Countries but if I select an item the default text will disappear and the item selected will be displayed, how can I fix this?

You could use a Combined Template (ref post)
<Window.Resources>
<ResourceDictionary>
<DataTemplate x:Key="NormalItemTemplate" >
<CheckBox IsChecked="{Binding IsChecked}" Content="{Binding Item.Name}" />
</DataTemplate>
<DataTemplate x:Key="SelectionBoxTemplate" >
<TextBlock>Select Countries</TextBlock>
</DataTemplate>
<DataTemplate x:Key="CombinedTemplate">
<ContentPresenter x:Name="Presenter"
Content="{Binding}"
ContentTemplate="{StaticResource NormalItemTemplate}" />
<DataTemplate.Triggers>
<DataTrigger
Binding="{Binding RelativeSource={RelativeSource FindAncestor,ComboBoxItem,1}}"
Value="{x:Null}">
<Setter TargetName="Presenter" Property="ContentTemplate"
Value="{StaticResource SelectionBoxTemplate}" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ResourceDictionary>
</Window.Resources>
<Grid>
<ComboBox ItemsSource="{Binding AvailableNations}"
SelectedItem="{Binding SelectedNation}"
ItemTemplate="{StaticResource CombinedTemplate}"
Width="160" Height="55" Margin="0, 0, 0, 15" >
</ComboBox>
</Grid>
The way it works is described in the original answer. Note that the suggested solution will only work when IsEditable is set to false, I assume that won't be a problem in your case. Second, to get the text displayed at start up I bound SelectedItem (e.g. to the first item in the collection).

From the comments, it sounds like you just want the Select Countries text to display at all times, even when an item is selected.
Personally I would just go the simple route and place a TextBox on top of the ComboBox, and hide the Display Text of the ComboBox by using a Transparent Foreground color.
Here's a quick example demonstrating it :
<Grid>
<ComboBox SelectedIndex="1" Foreground="Transparent">
<ComboBox.Resources>
<Style TargetType="{x:Type ComboBoxItem}">
<!-- Make sure ComboBoxItems don't have transparent text -->
<Setter Property="Foreground" Value="{StaticResource {x:Static SystemColors.ControlTextBrushKey}}" />
</Style>
</ComboBox.Resources>
<ComboBoxItem>Test 1</ComboBoxItem>
<ComboBoxItem>Test 2</ComboBoxItem>
<ComboBoxItem>Test 3</ComboBoxItem>
</ComboBox>
<TextBlock Text="Select Countries" Margin="4,3" IsHitTestVisible="False" />
</Grid>
And the results (note that SelectedIndex = 1)
I'm sure there's other ways too, such as overwriting the way it paints the display text, or changing the control template, but this seemed like the easiest to me.

Related

Conditional Context Menu Triggers

I currently have two buttons. One button is to Showappointments(), the other is ShowTask(). When either is clicked the FontWeight of that button goes to bold. Only one can be bolded at a time. I use that as the indicator to show which is being displayed.
The values are then displaye in a ListBox. I'm trying to have a condition such that when ShowTask fontweight is Bold it'll display the corresponding contextMneu for the Task, and it'll display a different set of contextmenus for Appointments.
<ListBox ItemsSource="{Binding FilteredEventsCollection}"
<Style TargetType="{x:Type ListBox}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=AppointmentBold}" Value="Bold">
<Setter Property="ContextMenu" Value="{StaticResource Menu1}"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel cal:Message.Attach="[Event MouseDoubleClick] = [Action Open()]">
<TextBlock Text="{Binding Date, StringFormat=g}" Foreground="Black" FontWeight="Bold" FontFamily="Segoe UI"/>
<TextBlock Text="{Binding Title}" />
<TextBlock Text="{Binding Company}" Foreground="Black"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
User Control Resources
<ContextMenu x:Key="TaskMenu">
<MenuItem>Open This Task</MenuItem>
</ContextMenu>
<ContextMenu x:Key="AppointmentMenu">
<MenuItem>Open This Appointment</MenuItem>
</ContextMenu>
This piece of code crashes right away, I'm wondering if I'm approaching correct and if I can get some guidance

Default text of combobox

i want a default text on my combobox as i have binded my combo box to certain list of items...here is my code of xaml file.
<ComboBox x:Name="ProjectComboBox"
Text="{Binding ProjectNameBinding}"
ItemsSource="{Binding projectList, ElementName=MainWin}"
SelectedValuePath="_id" DisplayMemberPath="_name"
SelectedItem="{Binding ProjectNameBindingClass, Mode=OneWayToSource}"
Width="130" Background="White" BorderThickness="1"
FontFamily="/TimeSheet;component/Resources/#Open Sans" FontSize="12"
Canvas.Right="159" Canvas.Top="8" Height="47">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding _name}" TextWrapping="Wrap"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
Have you tried Text Property
<ComboBox x:Name="ProjectComboBox"
IsEditable=True
Text="{Binding ProjectNameBinding}" ....../>
or
You can use SelectedIndex Property and set it to 0(SelectedIndex=0) which displays first item in Source given.
or
you can do like this as in the link How to display default text "--Select Team --" in combo box on pageload in WPF?
I achieved it atlast by taking a new textblock and applying a trigger on it,and using the IsNullConverter class it helped
<TextBlock Text="Select Project" IsHitTestVisible="False" FontFamily="/TimeSheet;component/Resources/#Open Sans" FontSize="14" Canvas.Right="191" Canvas.Top="22">
<TextBlock.Resources>
<Converters:IsNullConverter x:Key="isNullConverter"/>
</TextBlock.Resources>
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=ProjectComboBox,Path=SelectedItem,Converter={StaticResource isNullConverter}}" Value="False">
<Setter Property="Visibility" Value="Hidden"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
Try:
DefaultText="Not Specified"
edit ah sorry I was thinking of my control
have a read of this How to show text in combobox when no item selected?
Try this in page load or form load
comboBox.SelectedItem = null;
comboBox.Text = "---select an item---";

WPF ListBox select word with mouse

Is it possible to select single words with the mouse in a WPF ListBox control? When yes, how can I do that?
All hints are welcome :)
If you define an ItemTemplate for your ListBox, you can use a TextBox to display each item (assuming that your items are plain strings):
<ListBox ItemsSource="{Binding YourCollection}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding}" IsReadOnly="True" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
UPDATE >>>
I just tested it and had to make one change to set the Binding.Mode property to OneWay and it worked just fine. However, I noticed that the TextBox would stop each item from being selected, so added a Style to take care of that and styled the items a little bit too:
<ListBox ItemsSource="{Binding YourCollection}" Name="ListBox" HorizontalContentAlignment="Stretch">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding ., Mode=OneWay}" IsReadOnly="True">
<TextBox.Style>
<Style>
<Setter Property="TextBox.BorderThickness" Value="0" />
</Style>
</TextBox.Style>
</TextBox>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemContainerStyle>
<Style>
<Style.Triggers>
<Trigger Property="ListBox.IsKeyboardFocusWithin" Value="True">
<Setter Property="ListBoxItem.IsSelected" Value="True" />
</Trigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>

wpf combobox with custom itemtemplate text

I have ComboBox with custom ItemTemplate.
<ComboBox Height="20" Width="200"
SelectedItem="{Binding Path=SelectedDesign}"
ItemsSource="{Binding Path=Designs}" HorizontalAlignment="Left"
ScrollViewer.CanContentScroll="False">
<ComboBox.ItemTemplate>
<DataTemplate DataType="{x:Type formdesign:FormDesignContainer}">
<Rectangle Width="200" Height="100">
<Rectangle.Fill>
<ImageBrush ImageSource="{Binding Path=ImageThumb}" Stretch="Uniform" />
</Rectangle.Fill>
</Rectangle>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
This works well. However WPF tries to draw rectangle as Combobox Text. How can I set "text" for this template. By "text" I mean string or control which represent selected item and write into combobox when item is selected
In other words I'd like to do this:
But now I got this
Try setting SelectionBoxItemTemplate with a TextBlock.
Appears that SelectionBoxItemTemplate is read-only. So another approach is to override ItemContainerStyle.Template. Example
I found this solution by Ray Burns a good approach. You can define two DataTemplate one for Items in the drop down list and the other for the selected item which should be shown in the Combobox. The using a trigger and checking the visual tree it decide which one to use.
<Window.Resources>
<DataTemplate x:Key="NormalItemTemplate" ...>
...
</DataTemplate>
<DataTemplate x:Key="SelectionBoxTemplate" ...>
...
</DataTemplate>
<DataTemplate x:Key="CombinedTemplate">
<ContentPresenter x:Name="Presenter"
Content="{Binding}"
ContentTemplate="{StaticResource NormalItemTemplate}" />
<DataTemplate.Triggers>
<DataTrigger
Binding="{Binding RelativeSource={RelativeSource FindAncestor,ComboBoxItem,1}}"
Value="{x:Null}">
<Setter TargetName="Presenter" Property="ContentTemplate"
Value="{StaticResource SelectionBoxTemplate}" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</Window.Resources>
...
<ComboBox
ItemTemplate="{StaticResource CombinedTemplate}"
ItemsSource="..."/>
Add Textblock to the datatemplate and bind it
or add Contentpersenter on the rectangle
Edit:
it seems like i didn't got what you were tring to accomplish ,

ListBox , DataTemplate and Triggers

i got a DataTemplate for a listboxitem and i want to create a triger , so when a user click an item the background will change and also the label
my code:
<Window.Resources>
<Style x:Key="RoundedItem" TargetType="ListBoxItem">
<EventSetter Event="MouseDoubleClick" Handler="listViewItem_MouseDoubleClick" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border Name="ItemBorder" CornerRadius="10" BorderBrush="Black" BorderThickness="1" Margin="1" Background="Transparent">
<Label Name="ItemLabel" Foreground="Red" >
<ContentPresenter />
</Label>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="ItemBorder" Property="Background" Value="DeepSkyBlue" />
<Setter TargetName="ItemLabel" Property="Foreground" Value="Orange" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<DataTemplate x:Key="TitleTemplate" DataType="models:Title" >
<StackPanel>
<Image Source="{Binding ThumbFilePath}" Width="50" HorizontalAlignment="Center"/>
<Label Content="{Binding Name}" HorizontalAlignment="Center" />
<TextBlock Text="{Binding Description}" HorizontalAlignment="Center" TextWrapping="Wrap" Padding="5,5,5,5"/>
</StackPanel>
</DataTemplate>
</Window.Resources>
What happend is that the TextBlock change his color and not the label..
anyone know why ?
Thanks.
The TextBlock inherits the Foreground definition from its parents in the visual tree. The Label, on the other hand, defines the Foreground in its default style.
Your approach is "non-WPF-like" - you shouldn't wrap the ContentPresenter in a Label control.
The right approach depends on whether you want all text in the item to change its Foreground, or just the label?
[In both cases, there's no apparent benefit to using a Label in the data template - so I'll assume that the label is changed to TextBlock.]
If the answer to the above question is that all text should be changed: in the ControlTemplate of the ListBoxItem, in the trigger for IsSelected, from the seccond setter remove TargetName="ItemLabel" so the final setter is:
<Setter Property="Foreground" Value="Orange" />
This will change the foreground of the item that will affect the foreground of both TextBlocks in the data template.
If you want to affect just one of the TextBlocks:
1. remove the setter for the foreground from the control template
2. add a trigger to your data template:
<DataTemplate>
<StackPanel>
<Image .../>
<TextBlock x:Name="Text01" ..../>
<TextBlock x:Name="Text02" ..../>
</StackPanel>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}}" Value="True">
<Setter TargetName="Text01" Property="Foreground" Value="Orange"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
Side note: if you have to use Label control in your data template, bind its Foreground property to the Foreground of the list box item, like so:
<Label Foreground="{Binding Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}}"....../>
If this doesn't help, it means that your list box item inherits its foreground, so use:
<Label Foreground="{Binding TextElement.Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}}"....../>
I want to tack on to this that I was experiencing a similar problem where I'd added a ListBox.ItemTemplate to my ListBox, and the styling then did not apply to the text anymore.
What I was doing was trying to display a list of languages (CultureInfo) for the user to select from, however I wanted the native names to display, not the English name. For some reason, not all languages have their native names capitalized in their CultureInfo, and NativeName is the only instance of their name, so I needed to apply a function to the CultureInfo.NativeName to capitalize the names myself. To accomplish this, I added the ItemTemplate with a Data Template inside, on which I applied a converter.
<ListBox IsSynchronizedWithCurrentItem="True" VerticalAlignment="Center" MinHeight="200" x:Name="cbLanguages"
ItemsSource="{Binding Path=SupportedCultures, Mode=OneWay, Source={StaticResource CultureResourcesDS}}"
FontSize="24" HorizontalAlignment="Stretch" Width="300" Margin="10"
Style="{DynamicResource ListBoxTemplate}" ItemContainerStyle="{DynamicResource ListBoxItemStyle}">
<ListBox.ItemTemplate>
<DataTemplate>
<Label Content="{Binding Converter={StaticResource NativeNameConverter}}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
After a while of searching, I came across XAMeLi's answer here, and changed the Label I'd put in the DataTemplate to a TextBox, and the ListBoxItemStyle I'd created worked again.
Basically, Labels and TextBoxes have different traits that can be exploited, or can cause annoying issues in this case. Here's a good explanation with some examples of the differences: http://joshsmithonwpf.wordpress.com/2007/07/04/differences-between-label-and-textblock/

Categories

Resources