I'm a bit puzzled:
this works:
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Label Content="Rol" />
<ComboBox ItemTemplate="{StaticResource listRollen}"
Height="23" Width="150"
SelectedItem="{Binding Path=SelectedRol, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
ItemsSource="{Binding Path=allRollen, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>
and the property for SelectedRol is:
public TblRollen SelectedRol
{
get { return _selectedRol; }
set
{
if (_selectedRol != value)
{
_selectedRol = value;
OnPropertyChanged("SelectedRol");
}
}
}
But this doesn't work:
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Label Content="Soort" />
<ComboBox ItemTemplate="{StaticResource listSoorten}"
Height="23" Width="150"
ItemsSource="{Binding Path=allSoorten}"
SelectedItem="{Binding Path=SelectedProduct, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</StackPanel>
with following property SelectedProduct:
public TblProduktSoorten SelectedProduct
{
get { return _selectedPSoort; }
set
{
if (_selectedPSoort != value)
{
_selectedPSoort = value;
OnPropertyChanged("SelectedProduct");
}
}
}
somewhere in my code I set SelectedProduct = p.TblProduktSoorten and while debugging, I see the property gets set correctly...
Combobox inside a DataGrid?
If the combobox is in a DataGrid you must add this :
Mode=TwoWay, UpdateSourceTrigger=PropertyChanged
See this : https://stackoverflow.com/a/5669426/16940
Try to use not selected item but value path look at the code sample
<ComboBox Name="projectcomboBox" ItemsSource="{Binding Path=Projects}" IsSynchronizedWithCurrentItem="True" DisplayMemberPath="FullName"
SelectedValuePath="Name" SelectedIndex="0" Grid.Row="1" Visibility="Visible" Canvas.Left="10" Canvas.Top="24" Margin="11,6,13,10">
</ComboBox>
the binding property is
public ObservableCollection<Project> Projects
{
get { return projects; }
set
{
projects = value;
RaisePropertyChanged("Projects");
}
}
This might be related to the fact that apparently attribute order does matter, in your second case the ItemsSource and SelectedItem declarations are swapped.
If you set the SelectedProduct property when SelectedProduct is changed in the property changed event handler, you need to set this property asynchronously.
private void ViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "SelectedProduct")
App.Current.Dispatcher.InvokeAsync(() => SelectedProduct = somevalue);
}
My problem was caused by my own tired brain. Same symptom, maybe it will kick you into seeing your problem.
Setting the SelectedItem must be given an item in the List!! (duhh) Normally this happens naturally but I had a case I got a "Role" from another service (Same object type) and was trying to set it and expecting the combobox to change! ;(
instead of -
Roles = roles;
CurrentRole = role;
remember to do this -
Roles = roles;
CurrentRole = roles.FirstOrDefault(e=> e.ID == role.ID); //(System.Linq)
I don't know if you fixed it yet, but I encountered the same issue today.
It was fixed by making sure the collection for selecteditems was an ObservableCollection.
I think this problem is caused by the type of ItemSource and SelectedItem is mitchmatched.
For example, if the ItemSource is binded to a List of int and the SelectedItem is binded to a string. If you set selected item to null or empty string, the combobox cannot know what item is selected. So the combobox will show nothing.
This might be old but I have not seen the trick that did it for me; I had to add NotifyOnSourceupdate=true to my SelectedItem in the ComboBox
This had me stumped for a while inside a DataGrid, using SelectedItem. Everything was fine but I am deserializing the app state which loads the items and also has a selected item. The collection was there but the selected isn't actually visible until I used the Text="{Binding Path=Score.SelectedResult.Offset}"
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox ToolTip="Score offset results"
ItemsSource="{Binding Score.SearchResults,UpdateSourceTrigger=PropertyChanged}"
SelectedItem="{Binding Score.SelectedResult, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Text="{Binding Path=Score.SelectedResult.Offset}"
SelectedValuePath="Offset"
DisplayMemberPath="Offset"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
Related
I'm working in huge application and I have one small problem
My Application has two languages (Arabic / English).
I have ComboBox And I would like to change the display content according to the language.
This is my ComboBox XAML:
<ComboBox x:Name="cmbCustomerGroup" Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="5"
Margin="2" SelectedValuePath="CustomerGroupId" Validation.Error="Validation_Error"
SelectedValue="{Binding Path=CustomerGroupId, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged, NotifyOnValidationError=True}">
<!--<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"/>
</DataTemplate>
</ComboBox.ItemTemplate>-->
</ComboBox>
This is my method:
private void FillCustomerGroups()
{
var oClsCustomers = new ClsCustomerGroups();
var lstCustGrps = oClsCustomers.GetData();
cmbCustomerGroup.ItemsSource = lstCustGrps.ToList<TbCustomerGroups>();
cmbCustomerGroup.DisplayMemberPath = Helper.CurrLang == Helper.SystemLanguage.Arabic ? "CustomerGroupAName" : "CustomerGroupEName";
cmbCustomerGroup.SelectedValuePath = "CustomerGroupId";
}
I got this result:
This is my database:
This usually occurs when DisplayMemberPath is set wrong, or bindable property is not a string and has no overriden ToString() method.
Try add new property to your TbCustomerGroups, for example CurrentGroupName like this
public string CurrentGroupName => Helper.CurrLang == Helper.SystemLanguage.Arabic ? CustomerGroupAName : CustomerGroupEName;
Then set cmbCustomerGroup.DisplayMemberPath = "CurrentGroupName"
Also check that CustomerGroupAName and CustomerGroupEName are strings or have ToString() method
UPDATE
Also don't use <ComboBox.ItemTemplate> if you use DisplayMemberPath
Please help!
I did many research on the internet, but didn't find any solution for my question.
I have a form with foods. There is a grid on the form and with it I can navigate on the food table. There is a combobox on the screen (not in the grid) which contains the categories. The combobox is filled up with the categories from categories table. When I change the record on the datagrid every field updated on the form except the combobox.
first record
second record
So my question is: what I have to do to refresh the combobox, to show the saved category when I navigate on the grid?
In the category table the category has "id" field and in the food table there is a "categoryid" field.
I have this in the xaml file:
<ComboBox x:Name="categoryComboBox" Grid.Row="5" Grid.Column="1" Margin="3,4,20,0" Grid.ColumnSpan="3"
ItemsSource="{Binding Source={StaticResource categoryViewSource}}"
SelectedValuePath="CategoryId"
DisplayMemberPath="CatName"
SelectedItem="{Binding CategoryId, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Height="25" VerticalAlignment="Top">
<ComboBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel/>
</ItemsPanelTemplate>
</ComboBox.ItemsPanel>
</ComboBox>
As I can see you have a small error in your code. I should use the SelectedValue instead of SelectedItem. So change it and I think it will work properly. And in addition You don't need any workaround with the scaling as I suggested before.
Here is example:
XAML
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" >
<ComboBox x:Name="categoryComboBox" ItemsSource="{Binding Source={StaticResource categoryViewSource}}"
SelectedValuePath="CategoryId"
DisplayMemberPath="CatName"
SelectedValue="{Binding CategoryId, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Height="25" VerticalAlignment="Top">
<ComboBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel/>
</ItemsPanelTemplate>
</ComboBox.ItemsPanel>
</ComboBox>
<Button Content="Change Category" Command="{Binding SelectionChangedCommand}"></Button>
</StackPanel>
DataContext
public class MyComboDataContext:BaseObservableObject
{
private int _categoryId;
private ICommand _selectionChangedCommand;
public MyComboDataContext()
{
CategoryId = 1;
}
public int CategoryId
{
get { return _categoryId; }
set
{
_categoryId = value;
OnPropertyChanged();
}
}
public ICommand SelectionChangedCommand
{
get { return _selectionChangedCommand ?? (_selectionChangedCommand = new RelayCommand(SelectionChanger)); }
}
private void SelectionChanger()
{
CategoryId += 1;
if (CategoryId == 4)
CategoryId = 1;
}
}
Explanations:
First of all, this is an example that is simulating the update of a combo. Here the combobox selected value is changed on each button click. In your example the category selection should effect the combo selected value. So each time the grid category selection happens you should push selected category id into the property the combo SelectedValue is bound to it.
In order to help you please update your question with next things:
Are there any Binding expression errors in your output window?
How do you handle a DataGrid selection in your code.
How the data grid selection effects the combobox SelectedValue(it have to be selected value)?
Let me know if you need more help. And feel free to mark you question as answered if my answer was helpful.
I have a weird problem with something simple I suppose.
I have a combobox with two bindings set up - one for ItemsSource and another for SelectedItem.
The selected item is not working on initial startup, but then it works OK. Output does not indicate any binding problems, I have also set up a TextBlock with the same binding to see if it works - and it does.
Here's the code
<ComboBox IsSynchronizedWithCurrentItem="True" IsEditable="False"
Name="ProgramsCollectionComboBox"
SelectedItem="{Binding ElementName=ThisUc,
Path=SelectedProgram}"
ItemsSource="{Binding ElementName=ThisUc,
Path=ProgramsCollection}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<TextBlock Text="{Binding ElementName=ThisUc,
Path=SelectedProgram.Name, Mode=TwoWay}" />
The property:
private Program _selectedProgram;
public Program SelectedProgram
{
get
{
if (_selectedProgram == null)
{
_selectedProgram = new Program(Settings.Default.SelectedProgramPath);
}
return _selectedProgram;
}
set
{
_selectedProgram = value;
Settings.Default.SelectedProgramPath = SelectedProgram.PathProgramFolder;
RaisePropertyChanged("SelectedProgram");
}
}
It saves and reads the settings OK, the initial values is shown in the textblock below the combobox, when I change the selected item, the textblock is updated, the settings are changed and everything works fine - except for the fact that on app startup, selected item is not selected.
Thanks for help!
There are two reasons your initial binding is not working. First, as Jehof has mentioned himself, is the fact that you're setting your SelectedProgram to an item that is not part of the ProgramsCollection.
Furthermore, when you are setting the initial value of your SelectedProgram you are doing so in the getter, where PropertyChanged is not invoked and thus the binding will never be aware of that change. You can either invoke PropertyChanged when initializing it in the getter:
...
get
{
if (_selectedProgram == null)
{
_selectedProgram = _programsCollection?.FirstOrDefault();
RaisePropertyChanged("SelectedProgram");
}
return _selectedProgram;
}
...
Or even better, set the default value on the private field:
private Program _selectedProgram = _programsCollection?.FirstOrDefault();
...
The getter of your property SelectedProgram should return a value of your ProgrammsCollection and not a new instance if it is null.
If the value is not part of the collection that is bound to the combobox it is not displayed.
let me start by introducing my current setup:
I have a ListView that binds its SelectedItem property to the ViewModel, like this:
<ListView Name="FileListView" ItemsSource="{Binding ImageList}"
SelectionChanged="ImageSelectionChanged"
SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
SelectionMode="Single">
<ListView.ItemTemplate>
<DataTemplate>
<view:FileListItem />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
It's item template (view:FileListItem) is the following:
<Grid MouseDown="FileListItemMouseDown" KeyDown="FileListItemKeyDown">
....
<TextBlock Name="NewNameTextBlock"
Text="{Binding NewName}"
Grid.Column="2"
Visibility="{Binding TextBlockVisibility}" />
<TextBox Name="NewNameTextBox"
Text="{Binding NewName, UpdateSourceTrigger=PropertyChanged}"
Grid.Column="2"
Visibility="{Binding TextBoxVisibility}" />
</Grid>
The idea here is to switch on the TextBox and switch off the TextBlock when the corresponding ListView item is being edited. This works ok, but when I hit a particular key, I want the ListView to select the next item and put that item into editing mode. I catch the KeyDown event as seen above in the ItemTemplate and broadcast a message, which is caught in the DataContext of my ListView like this:
public ImageFile SelectedItem {
get { return _selectedItem; }
set { _selectedItem = value; NotifyPropertyChanged("SelectedItem"); }
}
public void SelectAndEditThisHandler (object x)
{
ImageFile file = x as ImageFile;
SelectedItem = file;
}
The result is that the selection actually changes for a split second, but then it changes back to the previous selection. I suspect some other UI elements might be handling my key-presses and doing something to change the selection back, but I can't figure out which elements and how to pinpoint them.
Any help would be greatly appreciated! Thanks!
EDIT:
As requested, the SelectionChanged handler:
private void ImageSelectionChanged(object sender, SelectionChangedEventArgs e)
{
System.Collections.IList filelist = FileListView.SelectedItems;
if (filelist.Count == 1)
{
ImageFile selectedFile = FileListView.SelectedItem as ImageFile;
Mediator.Instance.NotifyColleagues(Mediator.Operations.ImagePathSelected, selectedFile.OriginalPath);
}
}
The mediator message broadcast doesn't do anything related to these controls/this problem at all.
Hello I have been searching everywhere for a solution to this problem and cannot figure out a solution.
I have a combo box in a datagrid column that I want to bind it's itemsource to a list generated by a database.
I also want to bind the selected value to a separate table.
I have succeeded in doing this... but only sometimes. There is something not synchronized.
Here is some code
xaml:
<Grid.Resources>
<my:CategoriesProvider x:Key="categoriesProvider"/>
</Grid.Resources>
..........................................
<data:DataGridTemplateColumn Header="Category" Width="100" x:Name="cboDataCol">
<data:DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate x:Name="cboDataTemplate">
<ComboBox Name="cboCategories" SelectedItem="{Binding category, Mode=TwoWay}" ItemsSource="{Binding CategoriesList,Source={StaticResource categoriesProvider}}" DisplayMemberPath="name" SelectedValue="{Binding Path=category.id}" SelectedValuePath="id"/>
</DataTemplate>
</data:DataGridTemplateColumn.CellEditingTemplate>
</data:DataGridTemplateColumn>
C#:
public class CategoriesProvider : List<category>
{
MenuItems.MenuItemService.MenuItemServiceClient svc = new MenuItems.MenuItemService.MenuItemServiceClient();
ObservableCollection<category> allCategories;
public CategoriesProvider()
{
svc.getCategoriesCompleted += new EventHandler<getCategoriesCompletedEventArgs>(svc_getCategoriesCompleted);
svc.getCategoriesAsync();
}
public void svc_getCategoriesCompleted(object sender, getCategoriesCompletedEventArgs e)
{
//m_autoresetevent.Set();
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
allCategories = e.Result;
if (allCategories == null)
{
MessageBox.Show("NULL123");
}
});
}
Sometimes it seems that the control gets bound to the list before getItemsAsync is completed. Is there a solution to doing it this way, or should I give up and try something else?
Thanks
Try implementing INotifyPropertyChanged on your CategoriesProvider. Where is CategoriesList? That's what you should be notifying changed.