Populate a WPF Combobox from Service - c#

I am trying to populate my combobox from a service response. The service returns an array of object like following
MyService.FirmSocial[] firmSocialList = client.GetActiveSocialMediaTypes();
I have checked, the firmSocialList populates properly. I need to populate my combobox with these values.
I have tried this in my code behind
cbSocialMediaTypes.ItemsSource = firmSocialList;
cbSocialMediaTypes.DisplayMemberPath = "socialMediaValue";
cbSocialMediaTypes.SelectedValuePath = "socialMediaType";
I also tried the same thing on the XAML side, but all I am getting is bunch of empty strings in my combobox. The thing is though, the number of elements matches with the item count of the combobox (of empty strings).
And yes, the property names of the FirmSocial object is correct.
The FirmSocial class
public class FirmSocial
{
private int socialMediaType;
private string socialMediaValue;
public int SocialMediaType
{
get
{
return socialMediaType;
}
set
{
socialMediaType = value;
}
}
public string SocialMediaValue
{
get
{
return socialMediaValue;
}
set
{
socialMediaValue = value;
}
}
}
And I have also tried this in my XAML section;
<ComboBox x:Name="cbSocialMediaTypes" HorizontalAlignment="Left" Margin="56,8,0,0" VerticalAlignment="Top" Width="211"
ItemsSource="{Binding firmSocialList}"
DisplayMemberPath="socialMediaType"
SelectedValuePath="socialMediaType" />
Thanks.

DisplayMemberPath is case sensitive.
DisplayMemberPath="socialMediaType"
is saying trying to bind to your private field, not your public property. Try:
DisplayMemberPath="SocialMediaType"

The problem is that you set the DisplayMemberPath and the SelectedValuePath to a private fields instead of a public properties.
cbSocialMediaTypes.DisplayMemberPath = "socialMediaValue";
cbSocialMediaTypes.SelectedValuePath = "socialMediaType";
Change it to
cbSocialMediaTypes.DisplayMemberPath = "SocialMediaValue";
cbSocialMediaTypes.SelectedValuePath = "SocialMediaType";

Related

Binding combobox to another combobox

I have a problem with binding combobox to another combobox. I'm trying to dynamically pass a parameter (id) from first combobox to the method of initiating second combobox. For example, if I selected the first item in first combobox, then second combobox will initialize with parameter that selected from first combobox.
XAML:
<ComboBox Name="ItServiceCmbox" ItemsSource="{Binding ItServiceMetricsNames}" DisplayMemberPath="ServiceName" SelectedValuePath="ServiceId" />
<ComboBox Name="MetricCmbox" ItemsSource="{Binding SelectedItem.MetricId, ElementName=ItServiceCmbox}" DisplayMemberPath="MetricName" SelectedValuePath="MetricId"/>
C#:
public partial class MainWindow : Window
{
readonly MetricsValuesHelper _metricsValuesHelper = new MetricsValuesHelper(new Repository());
public static int SelectedService;
public static int SelectedMetric;
public ObservableCollection<ItServiceMetricsNames> ItServiceMetricsNames { get; set; }
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
SelectedService = Convert.ToInt32(ItServiceCmbox.SelectedItem);
ItServiceMetricsNames = new ObservableCollection<ItServiceMetricsNames>();
ItServiceMetricsNames.Add(new ItServiceMetricsNames()
{
ServiceId = _metricsValuesHelper.GetServiceId(),
ServiceName = _metricsValuesHelper.GetServiceName(),
MetricId = _metricsValuesHelper.GetMetricId(SelectedService),
MetricName = _metricsValuesHelper.GetMetricName(SelectedService)
});
}
}
And ItServiceMetricsNames class:
public class ItServiceMetricsNames
{
public List<int> ServiceId { get; set; }
public List<string> ServiceName { get; set; }
public List<int> MetricId { get; set; }
public List<string> MetricName { get; set; }
}
Is it possible? Thanks for any answers!
This is a messy, naive implementation I did last year that seemed to work. There's definitely a better way out there. Instead of trying to do any actual binding in my xaml I made event handlers. You may create event handlers for ComboBoxes that are triggered whenever the sending ComboBox loses focus, closes it's DropDown, changes selection, etc.
If you want one ComboBox dependent on another, you may make the dependent ComboBox disabled until a selection is made in the independent ComboBox. Once a selection is made, you populate and enable the dependent ComboBox with the appropriate data.
Event handlers in your code will look something like this:
private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
// Independent ComboBox is the sender here
ProcessComboBoxes(sender as ComboBox);
}
The ProcessComboBoxes method will look different depending on what you're trying to do. But, essentially, it will identify the target/dependent ComboBox that you want to conditionally populate -- do this either with a Dictionary that maps from ComboBox to ComboBox or something you find suiting. After identifying the target, you will clear any items previously added, and then repopulate with your new ones. Below is a method in pseudocode (practically).
private void ProcessComboBoxes(ComboBox senderBox)
{
ComboBox dependentBox = lookupDependent[senderBox];
var itemType = itemTypes[senderBox.selectedIndex];
var listOfItemsNeeded = lookupItemsByType[itemType];
dependentBox.Items.Clear();
foreach (string item in listOfItemsNeeded){
dependentBox.Items.Add(item);
}
dependentBox.IsEnabled = true;
}
Don't forget to add your eventhandlers to your xaml. Make sure to pay close attention to the call hierarchy of events and determine when exactly you want your dependent ComboBox to be repopulated.

C# Binding data to combobox

SOLVED: My frontcolor of the combobox was set to White, hence I didn't see them.
I know this has been asked alot, I've been searching on Google but haven't found a solution to my problem. Nothing seems to work.
I want to bind data to my combobox (which comes from a database) but it's always blank. But when I bind the same data to a list, data appears..
XAML
<ComboBox x:Name="cboCPType" Style="{StaticResource comboboxenright}" ItemsSource="{Binding CPTypeList}" DisplayMemberPath="Name" SelectedValue="SelectedPerson.JobRole.ID"/>
viewmodel
private ObservableCollection<ContactPersonType> _CPTypeList;
public ObservableCollection<ContactPersonType> CPTypeList
{
get
{
return _CPTypeList;
}
set
{
_CPTypeList = value;
OnPropertyChanged("CPTypeList");
}
}
model
private String _Name;
public String Name
{
get
{
return _Name;
}
set
{
_Name = value;
}
}
public static ObservableCollection<ContactPersonType> GetTypes()
{
ObservableCollection<ContactPersonType> lijst = new ObservableCollection<ContactPersonType>();
String sql = "SELECT * FROM ContactpersoonType";
DbDataReader reader = Database.GetData(sql);
while (reader.Read())
{
ContactPersonType cType = new ContactPersonType();
cType.Id = reader["ID"].ToString();
cType.Name = reader["Naam"].ToString();
lijst.Add(cType);
}
return lijst;
}
Well, you must have a class with a property named Name, but you don't show your code or what/where/how you actually initialize CPTypeList.
Have a look at this article I've wrote:
Understanding SelectedValue, SelectedValuePath, SelectedItem & DisplayMemberPath + Demo.
Hopefully it'll clear some things for you :)
Also, have a look at the end of this answer to make sure you have the datacontext set.

How to bind datatable value in combobox which has static value?

I have a ComboBox with few static values.
<ComboBox Name="cmbBoxField" Grid.Column="4" Grid.Row="2" Style="{StaticResource comboBoxStyleFixedWidth}" ItemsSource="{Binding}" ></ComboBox>
MVVMModle1.cmbBoxField.Items.Add(new CustomComboBoxItem("Text Box", "0"));
MVVMModle1.cmbBoxFieldType.Items.Add(new CustomComboBoxItem("Pick List", "1"));
MVVMModle1.cmbBoxFieldType.Items.Add(new CustomComboBoxItem("Check Box", "2"));
MVVMModle1.cmbBoxFieldType.Items.Add(new CustomComboBoxItem("Radio Button", "3"));
When I am saving the data in Database table it is getting saved.
((CustomComboBoxItem)(MVVMModle1.cmbBoxField.SelectedValue)).Value.ToString();
Now when I am trying to Edit my form and binding the value again to combobox it is not showing the value.
MVVMModle1.cmbBoxField.SelectedValue = dtDataList.Rows[0]["ControlList"].ToString().Trim();
Someone please help me in this. How to bind selected value to the combobox?
There are quite a few problems with your code here:
You are setting the ItemsControl.ItemsSource property to the default binding (bind to the current data context), which is incorrect unless the DataContext is any type that implements IEnumerable, which it probably isn't.
If this is correct because the DataContext is, for example, an ObservableCollection<T>, then you still have an issue because you are adding items statically to the ComboBox instead of whatever the ItemsSource is.
Also, the type of items you are adding are CustomComboBoxItem, which I'm going to assume inherits from ComboBoxItem. Either way, you can't say the SelectedValue is some string since the values in the ComboBox are not strings.
You should really not have a collection of CustomComboBoxItem's, but instead a custom class that is in itself it's own ViewModel.
Now that that's been said, here is a suggested solution to your problem:
<ComboBox ItemsSource="{Binding Path=MyCollection}"
SelectedValue="{Binding Path=MySelectedString}"
SelectedValuePath="StringProp" />
public class CustomComboBoxItem : ComboBoxItem
{
// Not sure what the property name is...
public string StringProp { get; set; }
...
}
// I'm assuming you don't have a separate ViewModel class and you're using
// the actual window/page as your ViewModel (which you shouldn't do...)
public class MyWPFWindow : Window, INotifyPropertyChanged
{
public MyWPFWindow()
{
MyCollection = new ObservableCollection<CustomComboBoxItem>();
// Add values somewhere in code, doesn't have to be here...
MyCollection.Add(new CustomComboBoxItem("Text Box", "0"));
etc ...
InitializeComponent();
}
public ObservableCollection<CustomComboBoxItem> MyCollection
{
get;
private set;
}
private string _mySelectedString;
public string MySelectedString
{
get { return _mySelectedString; }
set
{
if (String.Equals(value, _mySelectedString)) return;
_mySelectedString = value;
RaisePropertyChanged("MySelectedString");
}
}
public void GetStringFromDb()
{
// ...
MySelectedString = dtDataList.Rows[0]["ControlList"].ToString().Trim();
}
}
You could alternatively not implement INotifyPropertyChanged and use a DependencyProperty for your MySelectedString property, but using INPC is the preferred way. Anyways, that should give you enough information to know which direction to head in...
TL;DR;
Take advantage of binding to an ObservableCollection<T> (create a property for this).
Add your items (CustomComboBoxItems) to the ObservableCollection<T>.
Bind the ItemsSource to the new collection property you created.
Bind the SelectedValue to some string property you create (take advantage of INPC).
Set the SelectedValuePath to the path of the string property name of your CustomComboBoxItem.
Can you use cmbBoxField.DataBoundItem()? If not target the source from the selected value, i.e. Get the ID then query the source again to get the data.
(CustomComboBoxItem)MVVMModle1.cmbBoxField.DataBoundItem();
When you bind a datasource it is simpler to do it like this:
private List GetItems(){
List<CustomComboBoxItem> items = new List<CustomComboBoxItem>();
items.Add(new CustomComboBoxItem() {Prop1 = "Text Box", Prop2 = "0"});
//...and so on
return items;
}
Then in your main code:
List<CustomComboBoxItem> items = this.GetItems();
MVVMModle1.cmbBoxField.DisplayMember = Prop1;
MVVMModle1.cmbBoxField.ValueMember = Prop2;
MVVMModle1.cmbBoxField.DataSource = items;
This will then allow your selected value to work, either select by index, value or text
var selected = dtDataList.Rows[0]["ControlList"].ToString().Trim();
MVVMModle1.cmbBoxField.SelectedValue = selected;

WPF Data Binding TooWay XAML to C# and C# to XAML

I have XAML code:
<TextBox Name="textBoxMask1"/>
<TextBox Name="textBoxMask2"/>
<TextBox Name="textBoxMask3"/>
...
<TextBox Name="textBoxMask9"/>
and class in C#:
private static string mask1;
public static string Mask1
{
get { return mask1; }
set { mask1 = value; }
}
private static string mask2;
public static string Mask2
{
get { return mask2; }
set { mask2 = value; }
}
private static string mask3;
public static string Mask3
{
get { return mask3; }
set { mask3 = value; }
}
....
private static string mask9;
public static string Mask9
{
get { return mask9; }
set { mask9 = value; }
}
And I want to bind these TextBoxes with Properties -> textBoxMask1 with Mask1 etc.
Earlier I did this by TextChanged, but I want to make Binding. TooWay Binding, because I want to predefine Mask1, Mask2, Mask3, ..., Mask9 in another C# class, and maybe later change these values - also in some C# code - and I want my changes, to be visible in layout (XAML) and in C# code - so ex. changing Property Mask1 from C# will change Text in TextBox textBoxMask1, and changing Text in textBoxMask1 will change Property Mask1.
I don't understand, how to make connection (binding) between objects XAML and C#.
For a normal Binding you don't need your properties to be static, just public. Here an example:
C# code (for one property)
private string mask1;
public string Mask1
{
get { return mask1; }
set
{
mask2 = value;
RaisePropertyChanged("Mask1");
}
}
It's really important for the binding that the class containing the properties implements the INotifyPropertyChanged interface, and that you raise the corresponding event in the setter of each property. Another option is to make all properties DependecyProperty, but it is usually overkill.
As for the XAML:
<TextBox Name="textBoxMask1" Text="{Binding Mask1, Mode=TwoWay}"/>
(TwoWay Binding is the default for the Text property, but it does not hurt to put it explicitly).
Just make sure that the DataContext of the object containing your TexBoxes (usually an UserControl) is set to a valid instance of your C# class.
By the way, this is a very basic question, that's why you got a negative vote and no answers before mine. What is expected is that you ask a question that poses a real problem for you, with a very specific answer, not something like "teach me how to do this".
If this answers your question don't forget to mark it as answer (the "tick" mark on the top left). A vote up would be also appreciated.
Hope it helps, regards.

DataBinding Textbox.Text to a specific element of a string array

Delving into the wonderful world of .NET databinding. I have a textbox whose text property I want to bind to a specific element of a string array in another object. (The form contains a combobox that selects the index of the element).
In other words, I'd like to do something like this:
textBoxFictionShort.DataBindings.Add(
new Binding("Text", m_Scenario, "Fiction[int32.Parse(comboBoxSelector.Text)]"));
where m_Scenario contains the
public string[] Fiction { get; set; }
property that I source from. Obviously the Binding above won't retrieve my item. AFAIK I can't create properties that accept parameters. What's the elegant/correct solution for this when using databinding? I can think of several ugly-seeming workarounds (i.e. a string property in m_Scenario that references the array string I'm binding to, and a public function that updates the string property on the combobox SelectedIndexChanged event).
This is an excellent place to have a View Model. Here's another ViewModel link
What I would do is have the following in the ViewModel (that gets bound to by components on the view)
an IObservable property bound to the items source of the combo box, that you add/remove to depending on the size of the array
a int property for the selected index bound to the SelectedElement of the combo box. You would have to do the conversion from string to int when this property is being set.
a string property that is bound to the textbox.text (you could likely use a label here, by the by) that is updated each time the aforementioned int property for the selected index is changed.
If this at all confusing I can build up some pseudo code, but those three properties should work and get you what you want.
Edit - To add some code:
public class YourViewModel : DependencyObject {
public string[] FictionArray {get; private set;}
public IObservable<string> AvailableIndices;
public static readonly DependencyProperty SelectedIndexProperty=
DependencyProperty.Register("SelectedIndex", typeof(string), typeof(YourViewModel), new PropertyMetadata((s,e) => {
var viewModel = (YourViewModel) s;
var index = Convert.ToInt32(e.NewValue);
if (index >= 0 && index < viewModel.FictionArray.Length)
viewModel.TextBoxText=FictionArray[index];
}));
public bool SelectedIndex {
get { return (bool)GetValue(SelectedIndexProperty); }
set { SetValue(SelectedIndexProperty, value); }
}
public static readonly DependencyProperty TextBoxTextProperty=
DependencyProperty.Register("TextBoxText", typeof(string), typeof(YourViewModel));
public bool TextBoxText {
get { return (bool)GetValue(TextBoxTextProperty); }
set { SetValue(TextBoxTextProperty, value); }
}
public YourViewModel(string[] fictionArray) {
FictionArray = fictionArray;
for (int i = 0; i < FictionArray.Length; i++){
AvailableIndices.Add(i.ToString()));
}
}
}
This isn't perfect, but it should give you some idea how you could create a viewmodel with properties that you could bind to. So in your xaml you'd have something like:
<ComboBox ItemSource="{Binding AvailableIndices}" SelectedItem="{Binding SelectedIndex}"/>
<TextBox Text="{Binding TextBoxText}"/>
I think you are in WinForms (not WPF), in this case you could just bind directly to the ComboBox's SelectedValue property...
comboBox1.DataSource = m_Scenario.Fiction;
textBoxFictionShort.DataBindings.Add(new Binding("Text", comboBox1, "SelectedValue"));
Add BindingSource
...
bindingSource1.DataSource = m_Scenario.Fiction
.Select((x, i) => new {Key = i + 1, Value = x})
.ToDictionary(x => x.Key, x => x.Value);
comboBox1.DisplayMember = "Key";
comboBox1.DataSource = bindingSource1;
textBox1.DataBindings.Add("Text", bindingSource1, "Value");
}
}

Categories