How to get combobox selectedItem value using binding - combobox

My Combobox:
<pmControls:pmComboBox Grid.Row="3" Grid.Column="1" Margin="3"
SelectedItem="{Binding Applicable_For,Mode=Two Way}" DisplayMemberPath="Applicable_For"
SelectedValuePath="Applicable_For">
<pmControls:pmComboBoxItem Content="Parcel" ></pmControls:pmComboBoxItem>
<pmControls:pmComboBoxItem Content="Property"></pmControls:pmComboBoxItem>
</pmControls:pmComboBox>
Have Added 2 static items to combobox as parcel and property and want to get these values
using binding .
I have given binding to SelectedItem and my binding field is Applicable_For.
Using above code am getting value as null in Applicable_For.
EDIT: I have added Mode=Two Way for Selected Item which I have forgot before.
But not it getting value as namespace like 'PropMgmt.Controls.pmComboBoxItem'
Please Help..

Instead of adding static items to combo box you can create a collection for it. for ex. Create class like:
public class KeyValuePair
{
string key;
public string Key
{
get { return key; }
set { key = value; }
}
string value;
public string Value
{
get { return this.value; }
set { this.value = value; }
}
}
Then in your view model add following code:
ObservableCollection<KeyValuePair> applicable_For_KeyValues = new ObservableCollection<KeyValuePair>();
KeyValuePair k1 = new KeyValuePair() { Key = "1", Value = "Parcel" };
KeyValuePair k2 = new KeyValuePair() { Key = "2", Value = "Property" };
applicable_For_KeyValues.Add(k1);
applicable_For_KeyValues.Add(k2);
Then in xaml add following:
<pmControls:pmComboBox Grid.Row="3" Grid.Column="1" Margin="3"
ItemsSource="{Binding Applicable_For_KeyValues}"
SelectedValue="{Binding Applicable_For,Mode=TwoWay}" SelectedValuePath="Value">
<pmControls:pmComboBox.ItemTemplate >
<DataTemplate>
<TextBlock Text="{Binding Value}"></TextBlock>
</DataTemplate>
</pmControls:pmComboBox.ItemTemplate>
</pmControls:pmComboBox>
Hope this solve your problem.

Related

Binding ObservableDictionary to ComboBox (WPF)

I would have thought this question would have been answered already, but I am not finding it. I have a simple class:
public class BinanceEndpoint : ObservableObject
{
private string baseAddress;
private string socketBaseAddress;
public string BaseAddress
{
get { return baseAddress; }
set { baseAddress = value; RaisePropertyChangedEvent(nameof(BaseAddress)); }
}
public string SocketBaseAddress
{
get { return socketBaseAddress; }
set { socketBaseAddress = value; RaisePropertyChangedEvent(nameof(SocketBaseAddress)); }
}
}
I am then populating an ObservableDictionary with objects from that class:
private MainViewModel()
{
private BinanceEndpoint apiEndPoint;
private ObservableDictionary<string, BinanceEndpoint> endPoints = new ObservableDictionary<string, BinanceEndpoint>();
endPoints.Add("Binance.com", new BinanceEndpoint() { BaseAddress = "https://api.binance.com", SocketBaseAddress = "wss://stream.binance.com:9443", });
endPoints.Add("Binance.us", new BinanceEndpoint() { BaseAddress =
"https://api.binance.us", SocketBaseAddress = "wss://stream.binance.us:9443", });
endPoints.Add("Testnet", new BinanceEndpoint() { BaseAddress = "https://testnet.binance.vision", SocketBaseAddress = "wss://testnet.binance.vision", });
}
[JsonIgnore]
public ObservableDictionary<string,BinanceEndpoint> EndPoints
{
get { return endPoints; }
set { endPoints = value; RaisePropertyChangedEvent(nameof(EndPoints)); }
}
public BinanceEndpoint APIEndPoint
{
get { return apiEndPoint; }
set { apiEndPoint = value; RaisePropertyChangedEvent(nameof(APIEndPoint)); }
}
}
Then I am trying to populate a ComboBox from using the ObservableDictionary.
<ComboBox Grid.Column="1" ItemsSource="{Binding EndPoints}" DisplayMemberPath="Key" SelectedValuePath="Value" SelectedValue="{Binding Path=APIEndPoint, Mode=TwoWay}"/>
The issue I am having is that the SelectedValue does not update the value of the ComboBox when it is loaded. What am I doing wrong?
You should avoid binding to a Dictionary in the first place. There is a reason that there is no ObservableDictionary in the .NET library - since the year of release in 2002. I guess we agree that this is not because MS developers didn't know how to implement such a dictionary after all these years.
Your are using SelectedValuePath and SelectedValue wrong. SelectedValue returns the value of the property that SelectedValuePath is pointing to. SelectedValuePath provides a property path on the SelectedItem.
When you actively set the SelectedValue, then the control will try to find and select the item where the item's property specified by SelectedValuePath matches the value of SelectedValue.
When SelectedItem returns the selected item (instance), then SelectedValue returns the value of a property on this SelectedItem that is specified using SelectedValuePath.
For example: we bind to a Dictionary<string, BinanceEndpoint>. To display the Key of your Dictionary we specify the DisplayMemberPath (as an alternative to a DataTemplate).
The SelectedItem will hold KeyValuePair<string, BinanceEndpoint>.
To have the ComboBox.SelectedValue return the selected item's SocketBaseAddress value, we must set the SelectedValuePath to "Value.SocketBaseAddress":
<ComboBox x:Name="ComboBox"
ItemsSource="{Binding EndPoints}"
DisplayMemberPath="Key"
SelectedValuePath="Value.SocketBaseAddress" />
<!-- Display the selected item's SocketBaseAddress value -->
<TextBlock text="{Binding ElementName=ComboBox, Path=SelectedValue}" />
If you want the SelectedValue to return the BinanceEndpoint instance then set SelectedValuePath to "Value":
<ComboBox x:Name="ComboBox"
ItemsSource="{Binding EndPoints}"
DisplayMemberPath="Key"
SelectedValuePath="Value" />
<!-- Display the selected item's 'SocketBaseAddress' value -->
<TextBlock text="{Binding ElementName=ComboBox, Path=SelectedValue.SocketBaseAddress}" />

Set selected value of combobox

I want to set selected value of a combobox
I am receiving a DataTable from the database looking like this:
this Datatable is bound to this combobox.
<ComboBox
DisplayMemberPath="KommuneNavn"
SelectedValuePath="KommuneNr"
ItemsSource="{Binding KommuneNavne}"
SelectedValue="{Binding KommuneNr, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Margin="3"
IsEnabled="{Binding IsUdenlandskAdresse, Converter={StaticResource BooleanNotConverter}}" />
In my viewmodel I have a specific KommuneNr stored in a property. I would like to have my combobox set to show the KommuneNavn that matches with this KommuneNr.
Example:
I have the KommuneNr 101 stored in my viewmodel, the KommuneNavn that matches with this is København I would then like to have my combobox be set to København.
This was pretty difficult to explain, I hope I am making sense. Otherwise feel free to ask.
KommuneNavne must be an ObservableCollection, and in your ViewModel you should implement INotifyPropertyChanged (not described in this example)
<ComboBox
ItemsSource="{Binding KommuneNavne}"
SelectedValue="{Binding KommuneNr, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}"
DisplayMemberPath="KommuneNavn"
SelectedValuePath="KommuneNr"
/>
ViewModel
public class MyViewModel : INotifyPropertyChanged
{
public ObservableCollection<KommuneNavn> KommuneNavne
{
get { value = _kommuneNavne; } //=> _kommuneNavne;
set
{
_kommuneNavne = value;
OnPropertyChanged(nameof(KommuneNavne));
}
}
public long KommuneNr
{
get { value = _kommuneNr; } //=> _kommuneNr;
set
{
if (_kommuneNr == value) return;
_kommuneNr = value;
OnPropertyChanged(nameof(KommuneNr));
}
}
private void SetValue(int valueToSet)
{
KommuneNr = valueToSet;
}
}

WPF ComboBox databinding ItemsSource item.ToString() to property setter. Why?

For some reason when I bind a ComboBox to a list of POCOs, the property which is bound to SelectedValue is set twice:
With value = POCO.ToString()
With value = POCO.Key property, which is the intended behaviour
I have the following ComboBox that is bound to properties in my ViewModel:
<ComboBox ItemsSource="{Binding Path=AllowedClassifications}"
DisplayMemberPath="Value"
SelectedValue="{Binding Path=TargetGroup.Classification}"
SelectedValuePath="Key" />
The properties in ViewModel are defined as:
//ICollection is implemented by ObservableCollection<T>
//DataBaseFieldValue has two public properties: string Key, string Value
public ICollection<DatabaseFieldValue> AllowedClassifications
{
get { return _allowedClassifications; }
private set { _allowedClassifications = value; }
}
public Model.TargetGroup TargetGroup
{
get { return _targetGroup; }
private set { _targetGroup = value; OnPropertyChanged("TargetGroup"); }
}
TargetGroup.Classification is defined as:
public string Classification
{
get { return _classification; }
set
{
System.Diagnostics.Debug.WriteLine("Classification: " + value);
_classification = value;
OnPropertyChanged("Classification");
}
}
Debug output:
Classification:
MyNamespace.DatabaseFieldValue
Classification: 2
What's happening here? Am I doing this completely wrong?
Everything looks OK in your code, except for the fact that according to your XAML the property which is bound to SelectedValue should be set to the POCO.Key value rather than POCO.Value (as you wrote you expected). I have just created a test project with similar setup and everything works.
Alternatively, you could try using SelectedItem property of combobox in combination with ItemTemplate:
<ComboBox ItemsSource="{Binding Path=AllowedClassifications}"
SelectedItem="{Binding Path=TargetGroup.Classification}" >
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Value}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
In this case the TargetGroup.Classification property must be of type DatabaseFieldValue.

WPF MVVM Combox not retaining old value on Validation fail

i have a combox control which is bound to a property using MVVM. There is validation done in the set method on value change.. The problem is the value getting changed to new value even if the validation fails and not retaining the old value..
Below is the XAML:
<ComboBox Grid.Column="1" Grid.Row="1" Width="200" ItemsSource="{Binding Path=Applications, Mode=OneTime}" SelectedItem="{Binding RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Path=DataContext.Application, Mode=TwoWay}" Margin="3"></ComboBox>
Below is the View Model Code:
private string[] types = new string[] { "A", "B" };
private string application;
public ObservableCollection<string> Applications { get; private set; }
public Const() {
this.Applications = new ObservableCollection<string>(this.types.ToList());
}
public string Application {
get {
this.application = this.applicationSpecificRequirements.ContainsKey(Resources.ApplicationKey) ? this.applicationSpecificRequirements[Resources.ApplicationKey] : this.Applications[0];
return this.application;
}
set {
if (this.exchangeViewModel.CheckIfApplicationNameExistsOrIsEmptyAndAssign(this.InstanceName, value)) {
System.Windows.Application.Current.Dispatcher.BeginInvoke(
new Action(() => {
this.applicationSpecificRequirements[Resources.ApplicationKey] = this.application;
((IHaveOnPropertyChangedMethod) this).OnPropertyChanged("Application");
}), DispatcherPriority.ContextIdle, null);
return;
}
this.applicationSpecificRequirements[Resources.ApplicationKey] = value;
}
}
looks like you're missing OnPropertyChanged(...) at last line in property setter.

Why the databinding fails in ListView (WPF)?

I have a ListView of which ItemSource is set to my Custom Collection.
I have defined a GridView CellTemplate that contains a combo box as below :
<ListView
MaxWidth="850"
Grid.Row="1"
SelectedItem="{Binding Path = SelectedCondition}"
ItemsSource="{Binding Path = Conditions}"
FontWeight="Normal"
FontSize="11"
Name="listview">
<ListView.View>
<GridView>
<GridViewColumn
Width="175"
Header="Type">
<GridViewColumn.CellTemplate>
<DataTemplate>
<ComboBox
Style="{x:Null}"
x:Name="TypeCmbox"
Height="Auto"
Width="150"
SelectedValuePath="Key"
DisplayMemberPath="Value"
SelectedItem="{Binding Path = MyType}"
ItemsSource="{Binding Path = MyTypes}"
HorizontalAlignment="Center" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</ListView>
public MyType : INotifyPropertyChanged
{
string Key;
string Value;
public string Key { get { return _key; }
set { _key = value; this.OnPropertyChanged("Key"); } }
public string Value { get { return _value; }
set { _value = value; this.OnPropertyChanged("Value"); } }
public MyType ()
{
}
public MyType (string key, string value)
{
_key = key;
_value = value;
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
public void MoveUpExecuted()
{
int oldIndex = this.Conditions.IndexOf(_selectedCondition);
//Check if the selected item is not the first item
if (oldIndex != 0)
{
int newIndex = oldIndex - 1;
this.Conditions.Move(oldIndex, newIndex);
}
}
My Custom collection is the ObservableCollection.
I have a two buttons - Move Up and Move Down on top of the listview control . When user clicks on the Move Up or Move Down button I call Move method of Observable Collection.
But when I Move Up and Move Down the rows then the Selected Index of a combo box is -1.
I have ensured that selectedItem is not equal to null when performing Move Up and Move Down commands.
Please Help!!
I don't get this part:
I call MoveUp and MoveDown methods of
Observable Collection.
ObservableCollection does not have such methods, at least not to my knowledge? Neither has it a notion of a current item or similar.
My apologies if I have missed something that could possibly render this post as ignorant.
What you could do is instead of binding your ListView to an ObservableCollection, you could bind it to a ICollectionView (derived from your ObservableCollection). If you set IsSynchronizedWithCurrentItem=True on ListView, you won't need to bind SelectedItem, it will be automatically bound to CurrentItem on ICollectionView.
ICollectionView also implements MoveCurrentToNext and MoveCurrentCurrentToPrevious which can be bound from your buttons (via ICommand).
EDIT:
Now that new information is on the table, my above answer is not really relevant anymore. But I don't (yet) know the SO convention how to handle this, if I should delete the post entirely, edit out the above or just add the "new" reply. For now I'll edit this post.
I tried to recreate your project and your problem. Hopefully I have understood your problem right, and recreated it similarly at least.
As in the problem being the combobox not holding its value when it is being moved in the listview, it works for me.
Below are the relevant code (some of it hidden to avoid too much noise).
Does this help you?
public class MainWindowViewModel:INotifyPropertyChanged
{
private Condition _selectedCondition;
public ObservableCollection<Condition> Conditions { get; set; }
public Condition SelectedCondition
{
get
{
return _selectedCondition;
}
set
{
if (_selectedCondition != value)
{
_selectedCondition = value;
OnPropertyChanged("SelectedCondition");
}
}
}
...
public void MoveUpExecuted()
{
int oldIndex = this.Conditions.IndexOf(_selectedCondition);
//Check if the selected item is not the first item
if (oldIndex != 0)
{
int newIndex = oldIndex - 1;
this.Conditions.Move(oldIndex, newIndex);
}
}
And the condition class:
public class Condition : INotifyPropertyChanged
{
private MyType myType;
public ObservableCollection<MyType> MyTypes { get; set; }
public MyType MyType
{
get { return myType; }
set
{
if (myType != value)
{
myType = value;
OnPropertyChanged("MyType");
}
}
}
public Condition()
{
MyTypes = new ObservableCollection<MyType>() { new MyType() { Key = "1", Value = "One" }, new MyType() { Key = "2", Value = "Two" } };
MyType = MyTypes[1];
}
... etc
<ListView
SelectedItem="{Binding Path=SelectedCondition}"
ItemsSource="{Binding Path=Conditions}"
FontWeight="Normal"
FontSize="11"
Name="listview" Margin="0,32,0,0">
<ListView.View>
<GridView>
<GridViewColumn
Width="175"
Header="Type">
<GridViewColumn.CellTemplate>
<DataTemplate>
<ComboBox
Width="150"
SelectedValuePath="Key"
DisplayMemberPath="Value"
SelectedItem="{Binding Path=MyType}"
ItemsSource="{Binding Path=MyTypes}"
HorizontalAlignment="Center" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
<Button Content="Move up"
Command="{Binding MoveUpCommand}"
/>
Swap these lines:
SelectedItem="{Binding Path = SelectedCondition}"
ItemsSource="{Binding Path = Conditions}"
ItemSource needs to be before the SelectedItem
Did you try ItemsSource="{Binding Conditions}"

Resources