WPF unable to select enabled item within ComboBox - c#

I'm trying to create a ComboBox with some items within the selection list enabled and others disabled. Visually, I'm able to do this but when I select an item that is visually enabled, nothing happens.
XAML:
<ComboBox ItemsSource="{Binding EndpointModel.DisplayFormat}"
VerticalAlignment="Center" Margin="0,0,10,0"
SelectedItem="{Binding EndpointModel.SelectMediaFormat}">
<ComboBox.ItemContainerStyle>
<Style TargetType="ComboBoxItem">
<Setter Property="IsEnabled" Value="{Binding IsEnabled}" />
</Style>
</ComboBox.ItemContainerStyle>
<ComboBox.ItemTemplate>
<DataTemplate>
<ComboBoxItem>
<TextBlock Text="{Binding Name}" />
</ComboBoxItem>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
When I click on the selected item above, nothing happens - EndpointModel.SelectMediaFormat is not executed.
The moment I remove the ComboBox.ItemTemplate stanza, I can successfully select any enabled item, i.e.
<ComboBox ItemsSource="{Binding EndpointModel.DisplayFormat}"
VerticalAlignment="Center" Margin="0,0,10,0"
SelectedItem="{Binding EndpointModel.SelectMediaFormat}">
<ComboBox.ItemContainerStyle>
<Style TargetType="ComboBoxItem">
<Setter Property="IsEnabled" Value="{Binding IsEnabled}" />
</Style>
</ComboBox.ItemContainerStyle>
</ComboBox>
As you can see, i'm displaying the object reference. I can't figure out how to replace the above with the actual Names.
I'm quite new at WPF, as you can imagine :-)
Any suggestions would be appreciated.

Try using the DisplayMemberPath property to Name (The property that you want to display).
<ComboBox ItemsSource="{Binding EndpointModel.DisplayFormat}"
VerticalAlignment="Center" Margin="0,0,10,0"
SelectedItem="{Binding EndpointModel.SelectMediaFormat}"
DisplayMemberPath="Name">
<ComboBox.ItemContainerStyle>
<Style TargetType="ComboBoxItem">
<Setter Property="IsEnabled" Value="{Binding IsEnabled}" />
</Style>
</ComboBox.ItemContainerStyle>
</ComboBox>

Related

WPF comboboxitem foreground color change

I'm trying to change the color of the comboboxitem in wpf, but for some reason it doesn't change and I don't know why.
The items do get loaded I can tell and verify that but i don't see them there not white or black but the same color as the background of the combobox which is kinda gray.
This is what i have to change the comboboxitem color foregournd to black, but does not work.
<ComboBox Foreground="#FF000000" x:Name="cBox_nosave" Width="149.8192" Height="22" Canvas.Left="23.7296000000033" Canvas.Top="40.7904000000016">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Grid.Column="1" Margin="2, 1" Text="{Binding Name}" />
</DataTemplate>
</ComboBox.ItemTemplate>
<ComboBox.ItemContainerStyle>
<Style TargetType="{x:Type ComboBoxItem}">
<Setter Property="Foreground" Value="Black" />
</Style>
</ComboBox.ItemContainerStyle>
</ComboBox>
What do I need to do to change the foreground color to black?
working in wpf .net version 4.6.1
Try to set TextBlock foreground in item template
<ComboBox Foreground="#FF000000" x:Name="cBox_nosave" Width="149.8192" Height="22" Canvas.Left="23.7296000000033" Canvas.Top="40.7904000000016">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Foreground="Black" Grid.Column="1" Margin="2, 1" Text="{Binding Name}" />
</DataTemplate>
</ComboBox.ItemTemplate>
<ComboBox.ItemContainerStyle>
<Style TargetType="{x:Type ComboBoxItem}">
<Setter Property="Foreground" Value="Black" />
</Style>
</ComboBox.ItemContainerStyle>
</ComboBox>

Binding inside DataTemplate don't work

I am won to change View with DataTriger, but when bindings inside Triger don't work.
What i'm do wrong?
my style in resources
<Style x:Key="AgentPositionContentTemplateSelector" TargetType="{x:Type ContentControl}">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate >
<!--Agent name dont changed, Binding to "Agent" property dont work -->
<TextBlock Background="BlueViolet" Text="{Binding Agent}"></TextBlock>
</DataTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<!--But this binding work perfect! DataTemplate changed!-->
<DataTrigger Binding="{Binding Agent.PositionId, Converter={StaticResource IntToPositionDictionaryConverter} }"><!--Int to Enum-->
<DataTrigger.Value>
<enum:PositionDictionary>Merchandiser</enum:PositionDictionary>
</DataTrigger.Value>
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<!--And this binding don't work also!-->
<TextBlock Background="Aqua" Text="{Binding Agent}"/>
</DataTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
My View:
<ListBox Name="AgentsListBox" IsSynchronizedWithCurrentItem="True" SelectionMode="Single"
DisplayMemberPath="Agent" Grid.Column="0" ItemsSource="{Binding CCRTeamRows}"><!--SelectedItem="{Binding SelectedAgent}"-->
</ListBox>
<!--This also work correct-->
<TextBlock Text="{Binding Agent, Mode=OneWay, UpdateSourceTrigger=PropertyChanged }"></TextBlock>
<TextBlock Text="{Binding Position, Mode=OneWay, UpdateSourceTrigger=PropertyChanged }"></TextBlock>
<TextBlock Text="{Binding Claster, UpdateSourceTrigger=PropertyChanged }"></TextBlock>
<ContentControl Style="{DynamicResource AgentPositionContentTemplateSelector}" />
Please take me on right way.
In the DataTemplates you'll need to use RelativeSource binding up to the ListBoxItem and then use Path=DataContext.Agent:
Text="{Binding Path=DataContext.Agent, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}}}"

ComboBox with fixed Header

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.

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>

After Treeview Loaded Event in WPF

I have a TreeView in my WPF application. In runtime I am binding data to the Treeview. Each node in a treeview is associated with path. I should change the color of the TreeView element If the file in the path associated with the element has an error. Say I need to change it to RED.
So Since I am binding it on fly after the treeview is entirely loaded I should traverse the tree again and I should check the path contains any error for every element in the TreeView.
How can I navigate the entire Tree element one by one from parent to root child and perform the error checking operation for each node.
Tree in XAML:
<TreeView Grid.Column="0" Grid.Row="0" HorizontalAlignment="Stretch" Name="treeView1"
VerticalAlignment="Stretch"
SelectedItemChanged="treeView1_SelectedItemChanged" HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Top" BorderThickness="0,0,0,1" BorderBrush="LightGray">
<TreeViewItem Header="Head Tree" ItemsSource="{Binding MainComps}">
<TreeViewItem.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
<Setter Property="FontWeight" Value="Normal" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="FontWeight" Value="Bold" />
</Trigger>
<DataTrigger Binding="{Binding IsSelected}" Value="True">
<Setter Property="Foreground" Value="RED" />
</DataTrigger>
</Style.Triggers>
</Style>
</TreeViewItem.ItemContainerStyle>
<TreeViewItem.Resources>
<HierarchicalDataTemplate DataType="{x:Type TextBlock}" ItemsSource="{Binding Children}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Head Tree" />
</StackPanel>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type local:MainCompViewModel}" ItemsSource="{Binding Children}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Maincompname}" />
</StackPanel>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type local:FeatureViewModel}" ItemsSource="{Binding Children}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding FeatureName}" />
</StackPanel>
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type local:CompViewModel}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Component}" />
</StackPanel>
</DataTemplate>
</TreeViewItem.Resources>
</TreeViewItem>
</TreeView>
In code behind:
I have treeview selection changed event.
How can I have AfterTreeViewLoaded event. Something like this.
Void TreeviewLoaded()
{
//Identify error. Change the color
}
Thanks in advance..
When you create tree items you should have some list of root items and bind the list to your TreeView.ItemsSource.
Then at any time you can check the paths and set boolean HasError (the property should exist in your ItemViewModel). Tree item's backround can be changed by style, like this:
<Setter Property="Background" Value="{Binding HasError, Converter={StaticResource HasErrorToBackroundConverter}" />
UPD:
Please see the following article http://blog.clauskonrad.net/2011/04/how-to-make-hierarchical-treeview.html.
Your ItemViewModel is just like the Folder from the article.
The list of root items is m_folders. Like the Folder contains a FullPath, your ItemViewModel will contain Path alongside HasError property.
When you need to check the path, you recursively pass m_folders, read the path from it, check it and set HasError.

Categories

Resources