wpf binding combobox selectedvaluepath - wpf

I have a list of type string(selectedextensionvalue) in my viewmodel. How can I bind selectedvaluepath(which is also of type list string) of my combobox to selectedextensionvalue. I don't know the syntax. May anyone help?
Thanks in advance,
Bilge

If you have a collection of strings, so you do not need to use SelectedValuePath property. You can add some string field to your ViewModel of string type.
public string SelectedStringValue
{
get;
set;
}
and in xaml:
<ComboBox ItemsSource="{Binding Path=selectedextensionvalue}"
SelectedItem="{Binding Path=SelectedStringValue, Mode=OneWayToSource}" />
EDIT:
But, if you want ComboBox to select some special item (for example, which you store in the database), so property SelectedStringValue should to raise PropertyChanged notification in setter, and the xaml will be the following:
<ComboBox ItemsSource="{Binding Path=selectedextensionvalue}"
SelectedItem="{Binding Path=SelectedStringValue, Mode=TwoWay}" />

Related

MVVM WPF - ComboBox two way binding inside ItemsControl

I am working on this problem for about a day now.
For some reason I am unable to TwoWay bind a value to a ComboBox if it is inside a ItemsControl. Outside works just fine.
I have an ObservableCollection of int? in my ViewModel:
private ObservableCollection<int?> _sorterExitsSettings = new ObservableCollection<int?>();
public ObservableCollection<int?> SorterExitsSettings
{
get { return _sorterExitsSettings; }
set
{
if (_sorterExitsSettings != value)
{
_sorterExitsSettings = value;
RaisePropertyChanged("SorterExitsSettings");
}
}
}
My XAML:
<ItemsControl ItemsSource="{Binding SorterExitsSettings}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=ItemsControl}, Path=DataContext.ScanRouter.Stores}"
SelectedValue="{Binding Path=., Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" DisplayMemberPath="name" SelectedValuePath="id" IsEditable="True" />
</DataTemplate>
</ItemsControl.ItemTemplate>
So the ComboBox is populated with a list of stores. It works fine so far.
The ObservableCollection SorterExitsSettings even has some values set which are shown in the displayed ComboBoxes. So setting the SelectedValue also works.
However when I change a selection, SorterExitsSettings wont change. While when I implement the ComboBoxes(100) without an ItemsControl it suddenly works fine.
<ComboBox ItemsSource="{Binding ScanRouter.Stores}" DisplayMemberPath="name" SelectedValuePath="id" IsEditable="True" SelectedValue="{Binding SorterExitsSettings[0], Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
Even better when I implement the ComboBoxes using the ItemsControl and also the example ComboBox shown above. When I change the single ComboBox's value it will change the value of the ComboBox inside the ItemsControl, but not the other way around.
Did somebody encounter this problem before?
My guess was that the ItemsControl doesn't like the fact that I am binding my selected value to an item in a list. However when I bind directly to a ViewModel property(Store) it also doesn't work.
I also tried using SelctedItem instead of SelectedValue and populate the ObservableCollection with Store objects instead of int?.
The problem is that you're binding your ComboBox's SelectedValue directly to the collection elements which are type int ?. This won't work, binding targets have to be properties. Try wrapping your int ? values in a class and expose the value as a property of that class with a getter and setter, i.e. something like this:
private ObservableCollection<Wrapper> _sorterExitsSettings = new ObservableCollection<Wrapper>();
... etc...
And:
public class Wrapper
{
public int? Value {get; set;}
}
And finally:
<ComboBox ... SelectedValue="{Binding Path=Value, Mode=TwoWay...
Post back here if you still have problems.

Displaying cultures in combo box and selecting

I'm trying to display cultures in the combox box and I want the user to receive the DisplayName of the culture when selected but I get culture code ie 'en', 'ar' etc
The itemsource of the combo box is
ItemsSource="{Binding Path=SupportedCultures, Mode=OneWay}" SelectedItem="{Binding SelectedItem.Language}" SelectedValue="DisplayName" DisplayMemberPath="DisplayName"
SupportedCultures property
public static List<CultureInfo> SupportedCultures
{
get
{
return _SupportedCultures;
}
}
How can I get DisplayName in my selectedItem's Language property which is of type string?
SelectedItem requires the same kind of object that your ItemsSource is bound to, so don't use that. If you want to select by the value of a property, then use SelectedValue, and to tell WPF which property to check for that value, use SelectedValuePath:
ItemsSource="{Binding SupportedCultures, Mode=OneWay}"
SelectedValue="{Binding SelectedItem.Language}"
SelectedValuePath="DisplayName"
DisplayMemberPath="DisplayName"
Your code is almost correct. Your List is static. So, to bind to it, you should use {x:Static} source:
ItemsSource="{Binding Source={x:Static yournamespace:YourClassName}, Path=SupportedCultures, Mode=OneWay}"
DisplayMemberPath="DisplayName"
Note that SelectedItem="{Binding SelectedItem.Language}" binds your selected CultureInfo to your ComboBox's DataContext. So, in this case a DataContext of your ComboBox should have object SelectedItem with CultureInfo Language {get;set;} property. I don't think that's what you are looking for?)

Binding TwoWay to SelectedItem: "Wrong way" synchronization on initialization

I am trying to bind a property of my DataContext to the SelectedItem on a ComboBox like this:
<ComboBox x:Name="ElementSelector"
ItemsSource="{Binding Source={StaticResource Elements}}"
DisplayMemberPath="ElementName"
SelectedItem="{Binding ValueElement, Mode=TwoWay}">
where the Elements resource is a CollectionViewSource (don't know, whether this matters).
When everything is initialized, the property ValueElement of the DataContext is set to the first item in the CollectionViewSource. What I want, is to initialize it the other way around: I would like to set SelectedItem of the ComboBox to the value of the property or null if no matching item is contained.
How can this be done?
EDIT - Additional information:
The ComboBox is part of a DataTemplate:
<DataTemplate x:Key="ReferenceTemplate"
DataType="viewModels:ElementMetaReferenceViewModel">
<StackPanel Orientation="Horizontal">
<StackPanel.Resources>
<ResourceDictionary>
<views:ElementsForReferenceViewSource x:Key="Elements"
Source="{Binding DataContext.CurrentProject.Elements, ElementName=Root}"
ReferenceToFilterFor="{Binding}"/>
</ResourceDictionary>
</StackPanel.Resources>
<TextBlock Text="{Binding PropertyName}"/>
<ComboBox x:Name="ElementSelector"
ItemsSource="{Binding Source={StaticResource Elements}}"
DisplayMemberPath="ElementName"
SelectedItem=""{Binding ValueElement, Mode=TwoWay}" />
</StackPanel>
</DataTemplate>
The ElementsForReferenceViewSource simply derives from CollectionViewSource and implements an additional DependencyProperty which is used for filtering.
The DataContext of the items in the CollectionViewSource look like this:
public class ElementMetaReferenceViewModel : ViewModelBase<ElementMetaReference, ElementMetaReferenceContext>
{
...
private ElementMetaViewModel _valueElement;
public ElementMetaViewModel ValueElement
{
get { return _valueElement; }
set
{
if (value == null) return;
_valueElement = value;
Model.TargetElement = value.Model;
}
}
...
}
For people encountering the same issue
The above code works as expected. The solution was getting the stuff behind the scenes right. Make sure, that the instance of the ViewModel which is the value of the property you want to bind to is definitely contained in the CollectionViewSource.
In my case the issue was deserializing an object tree incorrectly, so objects were instantiated twice. Then for each object a distinct ViewModel was initialized and then obviously the value of the property was not contained in the list.
Remark
To check whether this is an issue in your case, you can try the following:
Override the ToString() methods of the ViewModels displayed in the ComboBox like this:
public override string ToString()
{
return "VM"+ Model.GetHashCode().ToString();
}
Then you can easily compare the items in the source collection with the value on your property. Not the most professional way, but it did the job for me.

DisplayMemberPath property of combo box not working as expected with source being a dictionary with custom key

I am having a ComboBox in wpf which is having its source as a IDictionary<Key, String> where 'Key' is the custom key. The ComboBox is defined as follows:
<ComboBox
x:Name="MD_PDIR_COMBO_SOURCE"
Grid.Row="0"
Style="{DynamicResource USButtonComboBoxStyle}"
Margin="14,5"
VerticalAlignment="Top"
HorizontalAlignment="Stretch"
ItemsSource="{Binding Path=SourcesComboList}"
DisplayMemberPath="Value"
SelectedValuePath="Key"
SelectedValue="{Binding Path=SelectedSource}"
SelectionChanged="MD_PDIR_COMBO_SOURCE_SelectionChanged"
/>
Now the issue I am facing is, although DisplayMemberPath is set to the "Value" of the dictionary which is a String, the Visual text being displayed in the combo box on selecting an item is BLANK/EMPTY.
Although all the desired functions on combo box selection change are happening correctly but the values/text is not shown after we select an item.
Kindly help!
Does your style set the ItemTemplate at all?
Setting DisplayMemberPath is a shortcut way of saying the ItemTemplate should be a TextBlock with it's Text bound to whatever is in DisplayMemberPath, so setting the ItemTemplate in addition to DispalyMemberPath will override it and make DisplayMemberPath useless
This work OK
public string Value{ get; set; }
This doesen't work !
public string Value;
Conclusion: DisplayMemberPath indicates a property of your item object not a field. Use getter and setter: { get; set; }
i assume that you have a dictionary like this?
SourcesComboList = Dictionary<string,string>();
if you just wanna check wether your Displaymemberpath works alter your combobox to this
<ComboBox Grid.Row="0"
ItemsSource="{Binding Path=SourcesComboList}"
DisplayMemberPath="Value"
SelectedValuePath="Key">
</ComboBox>
if this is working the problem is not DisplayMemberPath :)
I had the similar problem with internal property.
The DisplayMemberPath is working only for public properties.
I guess the issue with the original question might be ComboBox does not query the Dictionary to know its Item Type instead it looks at the individual Dictionary Item (not the Value) which does not have any Key and Value properties.

WPF Combobox is changing source via SelectedValue when ItemsSource is loaded

I have this combobox in my WPF window.
<ComboBox DisplayMemberPath="Description" SelectedValuePath="ID" ItemsSource="{Binding Source={StaticResource CvsPrinters}}" SelectedValue="{Binding CheckPrinterID}" />
My problem is that when loading the window, the SelectedValue binding is causing my source data to change to the first item in the ItemsSource, instead of setting the Combobox's SelectedValue to the appropriate item in the ItemsSource.
The CheckPrinterID is from a listview selection datacontext, and this problem only occurs to the item initially selected in that listview on load. When I select another item in the listbox, the combobox correctly selects the proper item and all is fine, but unfortunately my initial item has been updated and is now incorrect.
I guess you are trying to synchronize ListView and ComboBox through a common property. Try setting IsSynchronizedWithCurrentItem to True in ListView and make sure SelectedItem or SelectedIndex for ListView is set during load.
Try re-arranging ItemsSource before DisplayMemberPath.
If you have some flexibility in the DataContext object you could try changing the selected CheckPrinter property to be of the data object type instead of the ID and switch to using SelectedItem instead of SelectedValue (for some reason SelectedValue behaves differently, especially at initial load) and then extract the ID from that value in code.
If you can't use the CheckPrinter objects in your DataContext object for whatever reason, you could also go the opposite direction on the UI side by using a list of IDs as the ItemsSource, and again using SelectedItem. To get the list to show what you want in the ComboBoxItems you would then need to use an IValueConverter to pull out Description values based on IDs:
<ComboBox ItemsSource="{Binding Source={StaticResource CvsPrinterIds}}" SelectedItem="{Binding CheckPrinterID}" >
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock >
<TextBlock.Text>
<Binding>
<Binding.Converter>
<local:MyDescriptionLookupConverter Printers="{StaticResource CvsPrinters}"/>
</Binding.Converter>
</Binding>
</TextBlock.Text>
</TextBlock>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
and a simple converter to do the ID-Description lookup (add some null and cast checks):
public class MyDescriptionLookupConverter : IValueConverter
{
public IEnumerable<Printer> Printers { get; set; }
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return Printers.First(p => p.Id == (int)value).Description;
}
...
}

Resources