How do I make the WPF ComboBox items visible, but non-selectable? - c#

I am trying to make the items of my WPF comboBox visible (preferably greyed out) but not allow the user to select them using c# code.
I have tried the following:
comboBoxName.IsHitTestVisible = false
comboBoxName.Focusable = false
However, this prevents them seeing the contents of the comboBox all together. How would I make the contents visible but cannot be selected in c#?

Set an item container style that will disable each ComboBoxItem.
<ComboBox x:Name="comboBoxName" ItemsSource="{Binding Collection}">
<ComboBox.ItemContainerStyle>
<Style TargetType="{x:Type ComboBoxItem}">
<Setter Property="IsEnabled" Value="False"/>
</Style>
</ComboBox.ItemContainerStyle>
</ComboBox>
If you use code-behind, can define and apply the item container style like this.
var itemContainerStyle = new Style(typeof(ComboBoxItem));
var isEnabledSetter = new Setter(IsEnabledProperty, false);
itemContainerStyle.Setters.Add(isEnabledSetter);
comboBoxName.ItemContainerStyle = itemContainerStyle;

Related

How to make part of TreeViewItem Header bold?

I am trying to implement a simple search feature in SQL and wpf... I need to highlight only part of the next in results that has been entered in a TextBox.
So I do the search in SQL get the results and put them on a TreeViewItem that adds them to a TreeView. That all works but how would i go around making only a certain part of TreeViewItem Header bold?
I already know how to find where the part of the text I want bold is but i just need to make it bold.
TreeViewItem root_item = new TreeViewItem() { Header = "Users" };
FoundUsersTreeView.Items.Add(root_item);
while (sqlReader.Read())
{
TreeViewItem new_item = new TreeViewItem() { Header = sqlReader.GetString(0) };
root_item.Items.Add(new_item);
}
If you're going to use wpf for any substantial work, you should use MVVM.
Working directly with controls is OK for very simple stuff but the difficulty ramps up very quickly.
You should Bind data and template that into controls instead.
This is how WPF is intended to be used.
Work with the base data rather than controls.
If you take a look at this sample:
https://gallery.technet.microsoft.com/WPF-Highlight-Matching-71ad5a04
It works with a listview rather than treeview and highlights text by making the background red.
Not exactly what you need.
But the principle is the thing to look at.
You could easily change the listview used to a treeview.
Having said that, you only seem to have on level of items in your treeview, so you pretty much might as well use a listview anyhow.
Anyhow.
If you take a look, you'll see each item is split up using a regex so there's a separate RunHi viewmodel for each piece.
Matching pieces have IsMatch set to true on their RunHi.
These are templated into a horizontal listview - so it looks like one textblock but is in fact one or more arranged one after the other.
Each row of the listview is itself a listview.
You could of course make the header of each treeviewitem a listview if you particularly want a treeview.
A datatrigger is used to make the background yellow.
To make it bold instead you can just change that part:
<ControlTemplate TargetType="{x:Type ListViewItem}">
<TextBlock Text="{Binding Text}">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger Binding="{Binding IsMatch}" Value="True">
<Setter Property="FontWeight" Value="Bold"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</ControlTemplate>
You can achieve this using HeaderTemplate of your TreeViewItem. As you're adding TreeViewItem from code behind, you can use the Tag property to differentiate which one need to be set as Bold.
You can add below DataTemplate to your Resources.
DataTemplate
<DataTemplate x:Key="headerTemplate">
<TextBlock Text="{Binding}">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger Binding="{Binding Tag, RelativeSource={RelativeSource AncestorType=TreeViewItem, Mode=FindAncestor}}"
Value="True">
<Setter Property="FontWeight" Value="Bold"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</DataTemplate>
Code Behind
TreeViewItem root_item = new TreeViewItem() { Header = "Users" };
treeView.Items.Add(root_item);
while (sqlReader.Read())
{
var new_item = new TreeViewItem { Header = sqlReader.GetString(0), Tag = true };
new_item.HeaderTemplate = Resources["headerTemplate"] as DataTemplate;
root_item.Items.Add(new_item);
}
You can set boolean value to Tag property to make that Node as Bold.

How to add comboboxitem to combobox in style(WPF)

I want to create a combobox style.In the style, I want to add 10 comboboxitems(1, 2,3,...,10) in the combobox.So how can I make it?
Not sure why exactly you would want to do this, but you can of course assign a value to the ItemsSource property in a Style:
xmlns:sys="clr-namespace:System;assembly=mscorlib"
...
<x:Array x:Key="MyComboBoxItems" Type="sys:String">
<sys:String>1</sys:String>
<sys:String>2</sys:String>
<sys:String>3</sys:String>
<sys:String>4</sys:String>
</x:Array>
<Style TargetType="ComboBox">
<Setter Property="ItemsSource" Value="{StaticResource MyComboBoxItems}" />
</Style>
You can do it in XAML and in C#.
In C# for adding items in combox use this code in Loaded event of window:
comboboxname.Items.add("Item1");
comboboxname.Items.add("Item2");
comboboxname.Items.add("Item3");
for show default item use this :
comboboxname.SelectedIndex= number of Item(for example Item1 equals 0);

WPF ListView programmatically deselect item

I have used the following approach to bind IsSelected of my items to a Property: WPF ListView Programmatically Select Item
<ListView.ItemContainerStyle>
<Setter Property="IsSelected" Value="{Binding IsSelected}"/>
</ListView.ItemContainerStyle>
Now I am able to select my items in code behind by simple setting the IsSelected property to true. However I am not able to deselect items by setting the IsSelected property of my items to false.
Setting the items property IsSelected to true will trigger the ListViewSelectionChanged event. However setting the property IsSelected of an already selected item to false does not trigger the event. The property will be changed to false but the item remains selected within the ListView. I have also tried using Mode=TwoWay without any success.
I would appreciate any sort of help!
Thank you very much in advance,
Thomas
For OP or others looking to "programmatically" deselect a ListView.
If your ListView rigged up as Single, Extended or Multiple you can always just:
YourlistView.Selecteditem = null;
Or you can use this as well:
YourlistView.UnselectAll();
Looks like you are just missing the TargetType for the style. Add the target type of ListViewItem as per Kent's original code below.
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="IsSelected" Value="{Binding IsGroovy}"/>
</Style>
</ListView.ItemContainerStyle>

WPF DataGrid RowDetails Visibility binding to a property (with XAML only)

I have a DataGrid displaying bunch of Objects. Those objects have a property IsDetailsExpanded and I want to bind the DataRows DetailsVisibility property to that property.
My first approach works but requires some code-behind (which i would like to get rid of)
i handle the LoadingRow event
void LoadingRowHandler(object sender, DataGridRowEventArgs e)
{
Binding b = new Binding()
{
Source = e.Row.DataContext,
Path = new PropertyPath("IsExpanded"),
Converter = (IValueConverter)Resources["BoolToVisi"],
Mode = BindingMode.TwoWay
};
e.Row.SetBinding(DataGridRow.DetailsVisibilityProperty, b);
}
i think there has to be a way to achieve something similar in XAML but i unfortunately i have not the slightest clue. Any ideas? suggestions?
You can use a Style for the DataGridRow type, like so:
<DataGrid Name="dataGrid1" Margin="12,12,0,0">
<DataGrid.RowStyle>
<Style TargetType="DataGridRow">
<Setter Property="DetailsVisibility" Value="{Binding IsExpanded, Converter={StaticResource BoolToVisi}}" />
</Style>
</DataGrid.RowStyle>
</DataGrid>

Display a Default value for a Databound WPF ComboBox

I have a databound WPF comboxbox where I am using the SelectedValuePath property to select a selected value based on something other than the object's text. This is probably best explained with an example:
<ComboBox ItemsSource="{Binding Path=Items}"
DisplayMemberPath="Name"
SelectedValuePath="Id"
SelectedValue="{Binding Path=SelectedItemId}"/>
The datacontext for this thing looks like this:
DataContext = new MyDataContext
{
Items = {
new DataItem{ Name = "Jim", Id = 1 },
new DataItem{ Name = "Bob", Id = 2 },
},
SelectedItemId = -1,
};
This is all well and good when I'm displaying pre-populated data, where the SelectedItemId matches up with a valid Item.Id.
The problem is, in the new item case, where the SelectedItemId is unknown. What WPF does is show the combo box as blank. I do not want this. I want to disallow blank items in the combo box; I would like it to display the first item in the list.
Is this possible? I could write some code to explicitly go and set the SelectedItemId beforehand, but it doesn't seem right to have to change my data model because of a shortcoming in the UI.
I think you are going to have to do some manual work here to get this behavior. You could check in code behind when you first display the ComboBox whether or not the SelectedItemId matches up or not and then change the selected index based on that. Or if you know that the SelectedItemId will always be -1 when there is no corresponding item, you could use a datatrigger.
Method 1:
if (!DataContext.Items.Exists(l => l.Id == DataContext.SelectedItemId))
{
MyComboBox.SelectedIndex = 0; //this selects the first item in the list
}
Method 2:
<Style TargetType="ComboBox">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=SelectedItemId}" Value="-1">
<Setter Property="SelectedIndex" Value="0"/>
</DataTrigger>
</Style.Triggers>
</Style>
you may use this style trigger: if selecteditem is null,
first element is selected.
<Trigger Property="SelectedItem" Value="{x:Null}">
<Setter Property="SelectedIndex" Value="0"/>
</Trigger>

Categories