How to set "SELECT" option as first option in wpf comboBox - c#

I am using Enum Logic to populate the comboBox. The comboBox is populated correctly. But I want to set "--SELECT--" as the first option.
How can It be done??

put this in your xaml combobox
SelectedIndex="0"

Just modify your list before sending it to the view:
public List<string> YourList
{
get
{
if (_list[0] != "--Select--")
_list = _list.Insert(0, "--Select--");
return _list;
}
}

Try setting null value
<ComboBox SelectedItem="{Binding Item}" ItemsSource="{Binding Items}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock x:Name="displayText" Text="{Binding}" />
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding}" Value="{x:Null}">
<Setter TargetName="displayText" Property="Text" Value="--Select--" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
And VM:
public ObservableCollection<string> Items
{
get
{
return new ObservableCollection<string>
{
null,"1","2","3"
};
}
}
public string Item { get; set; }

Probably the simplest way would be to make ComboBox editable so that you can set custom text, and readonly so that items can only be selected:
<ComboBox IsEditable="True" IsReadOnly="True" Text="--SELECT--" />
Note that this will change the look of a control, so if that is a problem for you, you will have to use more complicated solution.

If your Class has a Property you want to display in the ComboBox take a look at following approach:
Set a namespace to your class:
xmlns:models="clr-namespace:Company.ProjectName.Models;assembly=Company.ProjectName.Models"
Then in your ComboBox add a new Item of your class like this:
<ComboBox DisplayMemberPath="Name" SelectedItem="{Binding BindingProperty, Mode=TwoWay}" >
<ComboBox.ItemsSource>
<CompositeCollection>
<models:CustomClass Name="--SELECT--" ID="0"/>
<!--<ComboBoxItem Background="LightGray" IsHitTestVisible="False" Height="1" Margin="7,0,7,0" IsEnabled="False" Focusable="False"/> !-->
<CollectionContainer Collection="{Binding Source={StaticResource ObservableCollection}}" />
</CompositeCollection>
</ComboBox.ItemsSource>

you could add the value(--SELECT--)to the data-table after retrieving data from database and set the selected index to 0.
DataRow row = dt.NewRow();
row["DATA"] = "--SELECT--";
dt.Rows.InsertAt(row, 0);
after bindingcombobox1.SelectedIndex = 0;

Related

Wpf multiple combobox binding to one property

I am having a data grid, one of its cells is a combo box like:
<DataGrid x:Name="Applications" RowStyle="{StaticResource CollapsedRow}" AutoGenerateColumns="false" CanUserAddRows="false" ItemsSource="{Binding Applications}">
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Content='˅' FontSize="9" Name="ExpanderButton" Click="OnGroupChange" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Width="181" Header="Name" Binding="{Binding Name, Mode=OneWay}" />
</DataGrid.Columns>
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding Path=DataContext.Cabins,
RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}}"
SelectedValuePath="Id" IsSynchronizedWithCurrentItem="True"
SelectedValue="{Binding Path=DataContext.SelectedCabin,
RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
mah:TextBoxHelper.Watermark="{Binding Path=DataContext.CabinsWatermark, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}}"
Height="2" Width="300" Margin="10 5 10 10" HorizontalAlignment="Left">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Converter={StaticResource GuidConverter}}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</DataTemplate>
</DataGrid.RowDetailsTemplate>
</DataGrid>
And as you see in each row there ia a combo box in detail row (expanded row using button), each combo box is binded to one property:
private Guid? selectedCabin;
public override Guid? SelectedCabin
{
get => selectedCabin;
set
{
selectedCabin = value;
if (value.HasValue)
{
Console.WriteLine(value);
}
OnPropertyChanged();
}
Now problem is when i select item in combo box i am getting not single value but couple of them (I suppose there are all values from one combo box I made a selection on), to make sure i double checked with test code behind:
private void ComboBox_OnSelectCabinChanged(object sender, RoutedEventArgs e)
{
var combo = (ComboBox)sender;
if (combo != null && combo.IsDropDownOpen)
{
((ApplicationsViewModel)DataContext).SelectedCabin = (Guid?)sender;
combo.IsDropDownOpen = false;
}
}
And I am getting here and combo box item list and casting exception. What could be the root cause of this and is there a way to bind multiple combo box values to one property, so is i select one it will override another.
It seems like you are binding the SelectedValue of all row details ComboBoxes to the same source property. And you can't cast the sender argument to a Guid?. Try to cast the SelecteedValue property of the ComboBox:
SelectedCabin = (Guid?)combo.SelectedValue;
If you don't want to handle the SelectionChanged event in the view, you could use an interaction trigger that executes a command that sets the source property. Please refer to this blog post for more information about this.

XAML Get Item text value from ListViewItem

I have a ListView Control witch item is composite by two TextBlocks like that:
<ListView x:Name="resultsList" ItemsSource="{Binding}" HorizontalAlignment="Left" Height="470" Margin="10,0,0,0" VerticalAlignment="Top" Width="342" FontSize="21.333" BorderThickness="0" ItemClick="RedirectPage" IsItemClickEnabled="True" SelectionMode="None">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,-4,0,-4">
<StackPanel.Resources>
<Style TargetType="TextBlock">
<Setter Property="Margin" Value="0,0,0,0" />
</Style>
</StackPanel.Resources>
<TextBlock FontSize="35" Text="{Binding target_name}" />
<TextBlock FontSize="15" Text="{Binding type_name}" Opacity="30" Margin="0, 0, 0 ,30"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
In the code behind I am trying to get as string the text value from first TextBlock element.
string targetName;
targetName = resultsList.SelectedItem.ToString();
I want that Variable "targetName" то assign the text value ( Text="{Binding target_name}" ) from first TextBlock in the ListView Item.
I will be very thankful if someone is able to help me.
resultsList.SelectedItem should be the object from the collection that is bound to the ListView. So, you can just cast it to the appropriate type and then access the target_name member
Itemssource should be collection. You need to typecast the collection to get the value.
class listData
{
public string target_name { get; set; }
public string type_name{ get; set; }
}
You can get values like this
listData ld= (listData)resultsList.SelectedItem;
string targetName =ld.target_name;

Need to get the selected item from Multiple select listbox in silverlight

I use the Following Code for Bind the values in Multiple select Listbox with Check box in silverlight
<ListBox x:Name="ValListBox" Margin="188,212,136,100" SelectionMode="Multiple">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding RelativeSource={RelativeSource AncestorType=ListBoxItem}, Path=IsSelected}" Content="{Binding}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I need to get the selected item text using c#?
By Using the Following Method We can get the Selected Item in multiselect Listbox.
Changes in xaml: We need to add Click Function.
<ListBox x:Name="ValListBox" Margin="188,212,136,100" SelectionMode="Multiple">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Click="CheckBox_Click" IsChecked="{Binding RelativeSource={RelativeSource AncestorType=ListBoxItem}, Path=IsSelected}" Content="{Binding}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
In Code Behind We can get like,
List<string> selecteditems = new List<string>();
private void CheckBox_Click(object sender, RoutedEventArgs e)
{
var cb = sender as CheckBox;
if (cb.IsChecked == true)
{
var item = cb.DataContext;
selecteditems.Add(item.ToString());
}
else
{
var item = cb.DataContext;
selecteditems.Remove(item.ToString());
}
}
In selecteditems List we can get the all selected items from Multiple Listbox

DataGridRow.IsSelected is set and I dont know why

Hello this is my problem:
I got two styles defined in the resources for DataGridRow and DataGridCell:
<Style TargetType="{x:Type DataGridRow}">
<Setter Property="DataGridRow.IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
</Style>
<Style TargetType="{x:Type DataGridCell}">
<Style.Triggers>
<Trigger Property="DataGridCell.IsSelected" Value="True">
<Setter Property="Background" Value="LightSteelBlue" />
</Trigger>
</Style.Triggers>
</Style>
I basically want a row to be highlighted blue when user selects it.
I got a MessageWrapper and a SignalWrapper class. Each MessageWrapper has a list of SignalWrappers (which can be empty sometimes). So the first DataGrid is to display all MessageWrappers:
<DataGrid x:Name="messageGrid"
Grid.Column="0"
Margin="3"
AutoGenerateColumns="False"
CanUserAddRows="False"
HorizontalScrollBarVisibility="Hidden"
IsReadOnly="True"
ItemsSource="{Binding SelectedBusWrapper.MessageWrappers}"
SelectedItem="{Binding SelectedBusWrapper.SelectedMessageWrapper}"
attachedProperties:SelectingItemAttachedProperty.SelectingItem="{Binding SelectedBusWrapper.MessageWrapperToScrollIntoView,
UpdateSourceTrigger=PropertyChanged,
Mode=TwoWay}">
<DataGrid.Columns>
<DataGridTemplateColumn Width="Auto" Header="Filter">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox MaxWidth="15"
MaxHeight="15"
CommandParameter="{Binding}"
IsChecked="{Binding Filter}"
Style="{StaticResource CheckBoxStyle}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Width="9*"
Binding="{Binding Message.Name}"
Header="Name" />
<DataGridTextColumn Width="9*"
Binding="{Binding HexId}"
Header="Id" />
<DataGridTextColumn Width="11*"
Binding="{Binding Message.Sender}"
Header="Sender" />
</DataGrid.Columns>
</DataGrid>
Each Row of this DataGrid has a CheckBox column. If no CheckBox at all is checked then all SignalWrappers are displayed in second DataGrid. If one or more are checked, then only the SignalWrappers of the checkec MessageWrappers should be displayed. Here the DataGrid:
<DataGrid Grid.Column="1"
Margin="3"
AutoGenerateColumns="False"
CanUserAddRows="False"
HorizontalScrollBarVisibility="Hidden"
IsReadOnly="True"
ItemsSource="{Binding SelectedBusWrapper.SelectedSignalWrappers}"
SelectedItem="{Binding SelectedBusWrapper.SelectedSignalWrapper}"
SelectionMode="Extended">
<DataGrid.Resources>
<Style TargetType="DataGridRow">
<Setter Property="IsSelected" Value="{Binding IsSelected}" />
</Style>
</DataGrid.Resources>
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDoubleClick">
<i:InvokeCommandAction Command="{Binding MouseDoubleClickCommand}" CommandParameter="{Binding}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<DataGrid.Columns>
<DataGridTemplateColumn Width="Auto" Header="Filter">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox MaxWidth="15"
MaxHeight="15"
CommandParameter="{Binding}"
IsChecked="{Binding Filter}"
Style="{StaticResource CheckBoxStyle}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Width="6*"
Binding="{Binding Signal.Name}"
Header="Name" />
<DataGridTemplateColumn Width="Auto" Header="Value">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox MinWidth="75"
IsEditable="True"
ItemsSource="{Binding Signal.Values.Values}"
SelectedItem="{Binding SelectedValue,
UpdateSourceTrigger=PropertyChanged,
Mode=TwoWay}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
Now if the user selects one or more message(s) in the first DataGrid the signals of those messages should be highlighted in the second. If the user selects a signal in the second, the parent message should be highlighted in the first DataGrid.
Bound Property of MessageWrapper class:
public bool IsSelected
{
get
{
return isSelected;
}
set
{
if (isSelected == value) {
return;
}
isSelected = value;
foreach (var item in SignalWrappers) {
item.IsSelected = value;
}
RaisePropertyChanged("IsSelected");
}
}
Bound Property of SignalWrapper class:
public bool IsSelected
{
get
{
return isSelected;
}
set
{
if (isSelected == value) {
return;
}
isSelected = value;
ParentMessageWrapper.IsSelected = value;
RaisePropertyChanged("IsSelected");
}
}
Now I have an odd behavoir I cannot understand:
When I check the first CheckBox in the first DataGrid:
The message gets highlighted, the second DataGrid shows only the signals of that message and highlights them. This is correct so far.
If I now check a second message it highlights both rows and all signals of those rows. While debugging i noticed what happens is that the first MessageWrappers IsSelectedflag gets set to false, and all its signals flag gets set to false, which is correct. Afterwards the second MessageWrappers flag gets set to true and all its signals flag gets set to true, which is correct too.
And afterwards for a reason I cannot understand a signal of the first MessageWrapper IsSelected flag is set to true, this will set the MessageWrappers flag to true and this will set the other signals flag to true.
Note: If I check the third CheckBox everything is working as expected again.
Can anybody understand why this is? Thanks for your help in advance!
you have many loops when setting IsSelected in SingleWrapper because it set ParentMessageWrapper.IsSelected = value; which will return to set IsSelected in SingleWrapper and so on.
i suppose to make Method in SingleWrapper Like this:
public SetIsSelected(bool value)
{
if (isSelected == value) {
return;
}
isSelected = value;
RaisePropertyChanged("IsSelected");
}
and change item.IsSelected = value; in MessageWrapper to item.SetIsSelected(value)

Multiple Listviews with only one SelectedItem

I have multiple Listviews each binded with their own itemsource. But i only have 1 Selected Item.
So for example i have 5 listboxes (Monday, Tuesday, ...) each of them with their own itemssource (MondayList, TuesdayList, ...). Each of these Listviews SelectedItem property is binded to The Property 'CurrentToDo'.
The problem is that if i select one in the Monday and then select one in Tuesday they are both selected.
So only one item should be able to be selected throughout all the listviews, please help.
<UserControl.Resources>
<Style x:Key="ListViewItemStyleToDo" TargetType="{x:Type ListViewItem}">
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}"/>
</Style>
<GridView x:Key="ViewBase1" x:Shared="False" >
<GridViewColumn Header="" Width="30">
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding IsSelected, Mode=TwoWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListViewItem}}}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Subject" Width="auto" DisplayMemberBinding="{Binding Subject}" />
</GridView>
</UserControl.Resources>
<ListView Grid.Row="1" ItemsSource="{Binding MondayList}" SelectedItem="{Binding CurrentToDo, Mode=TwoWay}" SelectionMode="Single" ItemContainerStyle="{DynamicResource ListViewItemStyleToDo}" View="{DynamicResource ViewBase1}" />
<ListView Grid.Row="3" ItemsSource="{Binding TuesdayList}" SelectedItem="{Binding CurrentToDo,Mode=TwoWay}" SelectionMode="Single" ItemContainerStyle="{DynamicResource ListViewItemStyleToDo}" View="{DynamicResource ViewBase1}" />
Property:
private ToDoMod _currentToDo;
public ToDoMod CurrentToDo
{
get { return _currentToDo; }
set
{
_currentToDo= value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("CurrentToDo"));
}
}
Here is the answer:
Just bind to SelectedValue instead of SelectedItem.
You'd need to add 5 more properties: MondayCurrentToDo, TuesdayCurrentToDo...
Bind each list view's SelectedItem to the respective property.
In setter of each property, update CurrentToDo and remove selection of other lists - so it will look like this:
private ToDoMod _mondayCurrentToDo;
public ToDoMod MondayCurrentToDo
{
get { return _mondayCurrentToDo; }
set
{
_mondayCurrentToDo= value;
CurrentToDo = _mondayCurrentToDo;
_tuesdayCurrentToDo = null;
//TODO: add null setters for all other _<dayOfWeek>CurrentToDo members
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("MondayCurrentToDo"));
PropertyChanged(this, new PropertyChangedEventArgs("TuesdayCurrentToDo"));
//TODO: add notificaitons for all other <DayOfWeek>CurrentToDo properties
}
}
}
Of course, refactor this into methods, etc...

Categories