My problem is that after I select a item in the ComboBox, the first item or "default" item of the combobox stays empty but if I click the combobox the values beneath show up are selectable etc. but I want the clicked one to show in the "default/first" place.
What I tried so far
XAML:
<ComboBox Margin="55,0,0,10" Height="20" Width="145" VerticalAlignment="Center" HorizontalAlignment="Left"
ItemsSource="{Binding TabItems, Source={StaticResource MainWindowViewModelRefactored}, Mode=TwoWay}"
SelectedItem="{Binding SelectedItem, Source={StaticResource MainWindowViewModelRefactored}, Mode=TwoWay}"
DisplayMemberPath="Header">
</ComboBox>
Property:
public TabItem SelectedItem {
get {
return _selectedItem;
}
set {
UpdateTCVCollection(value);
_selectedItem = value;
NotifyPropertyChanged("SelectedItem");
}
}
If I open up the combobox the selecteditem is highlighted, but I also want it to be shown in the "first place" when the ComboBox is closed.
You can add a method when the index has changed, then remove the item that the user selected and add it at the begining.
I've set the value of Sorted to false because that way the value you selected won't be reorganized in your ComboBox.
private void ComboBox1_SelectedIndexChanged(object sender, EventArgs e) {
RadItem selectedItem = ComboBox1.SelectedItem as RadItem;
if (selectedItem != null) {
ComboBox1.Items.Remove(selectedItem);
ComboBox1.Items.Sorted = true;
ComboBox1.Items.Sorted = false;
ComboBox1.Items.Insert(0, selectedItem);
ComboBox1.Text = selectedItem.Text;
}
}
Add the UpdateSourceTrigger to your Combobox.
UpdateSourceTrigger=PropertyChanged
Example:
<ComboBox Margin="55,0,0,10" Height="20" Width="145" VerticalAlignment="Center" HorizontalAlignment="Left"
ItemsSource="{Binding TabItems, Source={StaticResource MainWindowViewModelRefactored}, Mode=TwoWay}"
SelectedItem="{Binding SelectedItem, Source={StaticResource MainWindowViewModelRefactored}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
DisplayMemberPath="Header">
</ComboBox>
Have a look to this MSDN link
That should help you with your problem.
Greetings
Related
I'm trying to create an edit form for editing properties of a custom set of TV Series objects. One of the properties holds a collection of all owned media formats (DVD, Blu-ray, etc) for that particular series that will be displayed in a ComboBox. Items are added to the ComboBox via a separate popup window and items are to be removed from the ComboBox by selecting the item and clicking a remove Button.
I can add new entries to the MediaOwned ComboBox just fine, but when I try to select a specific ComboBox item to test the remove Button I find that I can only ever select the first entry. Can someone please tell me if I've missed something embarrassingly obvious, thanks.
Here is the problematic property:
private ObservableCollection<string> _mediaOwned = new ObservableCollection<string>();
public ObservableCollection<string> MediaOwned
{
get { return _mediaOwned; }
set
{
_mediaOwned = value;
OnPropertyChanged(new PropertyChangedEventArgs("MediaOwned"));
}
}
Here are the other relevant code behind:
private void Window_Loaded(object sender, RoutedEventArgs e)
{
// Create binding for the ListBox.
Binding listBinding = new Binding();
listBinding.Source = show.Series;
listBinding.Mode = BindingMode.OneWay;
listBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
lbSeries.SetBinding(ListBox.ItemsSourceProperty, listBinding);
// Create binding for the ComboBox.
Binding myBinding = new Binding();
myBinding.Path = new PropertyPath("MediaOwned");
myBinding.Mode = BindingMode.TwoWay;
myBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
cbMediaOwned.SetBinding(ComboBox.ItemsSourceProperty, myBinding);
}
private void btnRemoveMedia_Click(object sender, RoutedEventArgs e)
{
Series series = (Series)lbSeries.SelectedItem;
series.MediaOwned.Remove(cbMediaOwned.Text);
}
And here is the XAML code:
<Border Style="{StaticResource PanelBorderStyle}" DockPanel.Dock="Left" Margin="0,8,8,0"
DataContext="{Binding ElementName=lbLists, Path=SelectedItem}">
<DockPanel VerticalAlignment="Top">
<StackPanel>
<ListBox x:Name="lbSeries" Style="{StaticResource BasicListStyle}" Width="180" Height="300"
DisplayMemberPath="Title" SelectionMode="Single" LayoutUpdated="lbSeries_LayoutUpdated">
</ListBox>
</StackPanel>
<StackPanel x:Name="editPanel" DataContext="{Binding ElementName=lbSeries, Path=SelectedItem}">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0, 4, 0, 0">
<TextBlock Style="{StaticResource SmallFont}" Width="100">Title</TextBlock>
<TextBox x:Name="txtTitle" Style="{StaticResource TextBoxStyle}" Text="{Binding Path=Title, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Width="200" Margin="8, 8, 16, 8"></TextBox>
</StackPanel>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Top">
<TextBlock Style="{StaticResource SmallFont}" Width="100">Media owned</TextBlock>
<ComboBox x:Name="cbMediaOwned" Style="{StaticResource ComboBoxStyle}" Width="150" Margin="8,8,6,8"
></ComboBox>
<Button x:Name="btnAddMedia" Style="{StaticResource ToolbarButtonStyle}" Click="btnAddMedia_Click" Margin="0">
<StackPanel ToolTip="Add media">
<Image Source="Images/add.png" />
</StackPanel>
</Button>
<Button x:Name="btnRemoveMedia" Style="{StaticResource ToolbarButtonStyle}" Click="btnRemoveMedia_Click" Margin="4">
<StackPanel ToolTip="Remove media">
<Image Source="Images/remove.png" />
</StackPanel>
</Button>
</StackPanel>
</StackPanel>
</DockPanel>
</Border>
Alternatively I can also remove the binding code in the code behind and replace the ComboBox with the below code (but I still get the same problem - I can't select anything in the ComboBox):
<ComboBox x:Name="cbMediaOwned" Style="{StaticResource ComboBoxStyle}" Width="150" Margin="8,8,6,8" ItemsSource="{Binding ElementName=lbSeries, Path=SelectedItem.MediaOwned, UpdateSourceTrigger=PropertyChanged}"
SelectedItem="{Binding SelectedMedia, UpdateSourceTrigger=PropertyChanged}"></ComboBox>
SelectedMedia property:
private string _selectedMedia = "";
public string SelectedMedia
{
get { return _selectedMedia; }
set
{
_selectedMedia = value;
OnPropertyChanged(new PropertyChangedEventArgs("SelectedMedia"));
}
}
Here is my xaml:
<ComboBox x:Name="Models_ComboBox"
Width="110"
Text="Model"
ItemsSource="{Binding Models}"
SelectedItem="{Binding SelectedModel}"
DisplayMemberPath="Model"
MouseDoubleClick="Models_ComboBox_MouseDoubleClick"
SelectionChanged="Models_ComboBox_SelectionChanged"/>
Here are my VM properties:
private DataTable models;
public DataTable Models
{
get { return models; }
set
{
if (models != value)
{
models = value;
OnPropertyChanged(nameof(Models));
}
}
}
and
private DataRowView selectedModel;
public DataRowView SelectedModel
{
get { return selectedModel; }
set
{
if (selectedModel != value)
{
selectedModel = value;
if (value != null)
{
InitializeOptions(value["Model"].ToString());
}
OnPropertyChanged(nameof(SelectedModel));
}
}
}
As you can see, the ItemsSource and the SelectedItem of the ComboBox are bound to two different properties in the ViewModel. The ItemsSource is bound to a DataTable populated from a Database. Once the user selects a Model, then there are other option ComboBoxes that are populated based on that selection.
Fixed the problem myself. I had a line of code that was automatically setting the SelectedIndex of the ComboBox without me realizing.
I need the ComboBox below to keep the SelectedItem when I edit the text, at the moment as soon as I edit the text the SelectedItem turns null.
<ComboBox x:Name="FilterGroups"
IsEditable="True"
DisplayMemberPath="Code"
Text="{Binding FilterGroupCode}"
ItemsSource="{Binding FilterGroups}"
SelectedItem="{Binding SelectedFilterGroup}"
Margin="10,0"/>
My goal is to detect that the item has been edited, currently I have no idea which item was edited since the SelectedItem becomes null.
And a null SelectedItem to me at the moment means "New" item.
As AGH's Comment.
Xaml
<ComboBox x:Name="myFilterGroups"
ItemsSource="{Binding FilterGroups}"
DisplayMemberPath="Name"
SelectedItem="{Binding SelectedFilterGroup}"
IsEditable="True" Height="20"
LostFocus="myFilterGroups_LostFocus"
>
</ComboBox>
Code Behind
private void myFilterGroups_LostFocus(object sender, RoutedEventArgs e)
{
var selItem = myFilterGroups.SelectedItem;
if (selItem == null)
// Create New Item
;
}
I have a Window with ListBox on the left Side and TextBox on the right Side. The Textbox is binding to the Selected Item of the ListBox. The Textbox has a SaveContentCommand.
If you leave the Textbox with Enter or the Tab the SaveContentCommand is executed correct. But if i use the mouse to select something else the selecteditem is changed and then the SaveContentCommand is executed. This means the SaveContentCommand is used on another item.
I have tried to hack something like RenameLastSelectedItem()
But is there a correct/better way?
My List:
<customControls:MyListBox x:Name="UserListBox"
Grid.Row="1"
Grid.Column="0"
ItemsSource="{Binding Users}"
SelectedItem="{Binding SelectedItem, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
VerticalAlignment="Top"
Style="{DynamicResource MyListBoxStyle}"
ItemContainerStyle="{DynamicResource MyListBoxItemUserListStyle}">
My TextBox:
<customControls:MyTextBox x:Uid="textBoxName"
x:Name="textBoxNameOfSelectedItems"
Text="{Binding SelectedItem.Name, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=true, Mode=TwoWay}"
focus:FocusExtension.IsFocused="{Binding SelectedItem.IsNameFocused, Mode=TwoWay}"
focus:FocusExtension.EnableSelection="True"
UseKeyboardBinding="true"
Style="{DynamicResource MyTextBoxStyle}"
SaveContentCommand="{Binding SelectedItem.UpdateCommand}"
In the set method of the SelectedItem, save the previous item. This code will run when the selected item is changed when selecting a new item with the mouse..
SelectedItem
{get { return _selectedItem;}
set
{
//null check
SaveContent(_selectedItem);
_selectedItem = value;
}
}
I have 2 combobox master-slave in this way:
<ComboBox ItemSource="{Binding MySource}" SelectedItem="{Binding MySelectedItem}" DisplayMemberPath="Description" />
<ComboBox ItemSource="{Binding MySelectedItem.Items}" IsSynchronizedWithCurrentItem="{x:Null}" />
But when I select one item of first combobox which it has empty list of Items after I have selected one of them with Items and selected item in second combobox. The text in second combobox is not empty. I have tried with IsSynchronizedWithCurrentItem="False" too.
What is the problem?
I am not sur to understand what you are trying to say... But I am pretty sur that you didn't notify a PropertyChanged after modify your "MySelectedItem" and you forget the mode=TwoWay...
If you want to use the SelectedItem in your ViewModel:
Xaml:
<ComboBox ItemSource="{Binding MySource}" SelectedItem="{Binding MySelectedItem, mode=TwoWay}" DisplayMemberPath="Description" />
<ComboBox ItemSource="{Binding MySelectedItem.Items}"/>
ViewModel:
private YourItemType _mySelectedItem;
public YourItemType MySelectedItem
{
get { return (_mySelectedItem);}
set
{
if (_mySelectedItem != value)
{
_mySelectedItem = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("MySelectedItem"));
}
}
}
If you just want to do a filtering:
<ComboBox ItemSource="{Binding MySource}" DisplayMemberPath="Description" name="source"/>
<ComboBox ItemSource="{Binding SelectedItem.Items, ElementName=source}"/>
I have found the problem, it was that I have associated a command with interactivity in the combobox and this was catching an exception and didn't continue with the execution.
I have the following view.xaml and I bind a collection(SavedTracksCollection from viewmodel) to this list box and it displays the items in UI.
<phone:PanoramaItem Name="MusicTracks" Header="Saved Tracks" >
<Grid>
<ListBox x:Name="list" ItemsSource="{Binding SavedTracksCollection}" SelectedItem="{Binding SelectedItemTrack,Mode=TwoWay}">
<ListBox.ItemTemplate>
<DataTemplate>
<Button Background="Red" >
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding TrackTitle}"/>
<TextBlock Text="{Binding TrackUri}"/>
</StackPanel>
</Button>
<DataTemplate>
</ListBox.ItemTemplate>
</Grid>
</phone:PanoramaItem>
And the i have the following property defined in my viewmodel(this viewmodel is set as data context for my view) for the selecteditem binding "SelectedItemTrack".And i am binding SavedTracksCollection to the itemsource of the list.
private SavedTracksModel _SelectedItemTrack;
public SavedTracksModel SelectedItemTrack
{
get {
return _SelectedItemTrack;
}
set
{
if (value!=null)
_SelectedItemTrack = value;
//RaisePropertyChanged("SelectedItemTrack"); I dont think we need this.Let me know otherwise.
}
}
private List<SavedTracksModel> _SavedTracksCollection = new List<SavedTracksModel>();
public List<SavedTracksModel> SavedTracksCollection
{
get
{
return GetSavedTracks();
}
set
{
this._SavedTracksCollection = value;
RaisePropertyChanged("SavedTracksCollection");
}
}
But i am not able to determine how do i capture the SelectedITem event when user selectes an item from the Listbox .Currently it doesn't trigger the set method of the SelectedITemTrack .Once i capture the event with the details of selected item binding "TrackUri" i want to go to a new page where i can play the track.
any idea how to fix the issue ?
The first solution I can think of, why not just use the SelectionChanged event on ListBox?
<ListBox x:Name="list" ItemsSource="{Binding SavedTracksCollection}"
SelectedItem="{Binding SelectedItemTrack,Mode=TwoWay}"
SelectionChanged="List_OnSelectionChanged"/>
// in code behind
private void List_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
// navigate here after validating the selected item
// or raise Command in your ViewModel programatically
}