Problem with Combobox binding to ObservableCollection in MVVM - c#

I have a little problem and I don't know how to fix it.
In my View I have a combobox, that should be able to display the property "Name" of the ObservableCollection "Phases". I already tried to show a single "Name-property" without a Datatemplate and it worked. I think I messed something up with the binding in the DataTemplate. What is wrong? Can you help me?
Here is my View:
<ComboBox ItemsSource="{Binding Phases}"
SelectedItem=""
Width="100" HorizontalAlignment="Left"
Margin="50,20">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}"/>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
Here my ObservableCollection:
public ObservableCollection<PhaseViewModel> Phases
{
get;
}
And here the property inside Phases:
public string Name
{
get { return myName; }
set { myName = value;}
}

Related

Binding Itemscontrol item

My XAML is as under. I have a main ViewModel which has a list of items and I want to display a property within this list
<ItemsControl ItemsSource="{Binding MyList}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Label Content="{Binding MyName, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"></Label>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
The problem is that MyName is always blank although my list has two items.
The main VM class has this property below and I add items in the constructor
public ObservableCollection<InnerViewModel> MyList { get; set; }
My inner VM has
public class InnerViewModel
{
private string _MyName;
public string MyName
{
get
{
return _MyName;
}
set
{
_MyName = value;
OnPropertyChanged("MyName");
}
}
I do have OnPropertyChanged in place but I'm not pasting it here for simplicity. I think the problem is with the XAML but I'm not sure. How do I get the property MyName to be displayed in my list of items in the view?
Since you use MyList as the ItemsSource, the data source for the child elements will be MyList. So you do not need to use the RelativeSource.
In other words, this should work :
<ItemsControl ItemsSource="{Binding MyList}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Label Content="{Binding MyName}"></Label>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Try and remove the relative source part of the binding.
<DataTemplate>
<Label Content="{Binding MyName}"></Label>
</DataTemplate>

WPF - How to view a property name in comboboxitem list

I have a combobox that is binded to collection called Models but it shows the ToString value instead of Name property
<xctk:WatermarkComboBox x:Name="cb_Model" ItemsSource="{Binding Models}" DisplayMemberPath="Name" SelectedValue="{Binding SelectedModel}" Grid.Column="2" Grid.Row="2" Watermark="Vehicle Model"/>
private ObservableCollection<tbl_Model> _models;
public ObservableCollection<tbl_Model> Models
{
get { return _models; }
private set {
_models = value;
NotifyPropertyChanged("Models");
}
}
tbl_Models properties :
Model_No
Name
Manufacturer
The comboboxitem isnt displaying the name property.How can i achieve it without overriding the ToString() method ? Thanks in advance
Seems that it is a bug in WatermarkComboBox. Just specify DataTemplate explicitly, instead of setting DisplayMemberPath:
<xtck:WatermarkComboBox x:Name="cb_Model" ItemsSource="{Binding Models}" SelectedValue="{Binding SelectedModel}" Watermark="Vehicle Model">
<xtck:WatermarkComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</xtck:WatermarkComboBox.ItemTemplate>
</xtck:WatermarkComboBox>

ListView Data Binding

I'm writing simple WPF Application and I wanted to use ListView to display List of items. My code is:
WPF.xaml
<ListView Grid.Column="0" Grid.Row="1" Margin="10,0,10,5" ItemsSource="{Binding MyCollection.Elements}">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding ElementDescriptions}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
WPF.xaml.cs
public MyViewModel ViewModel
{
get { return DataContext; }
set { DataContext = value; }
}
MyViewModel.cs
public OwnedCollection Elements { get; set; }
OwnedCollection.cs
public List<ElementDescriptions> ElementDescriptions { get; set; }
I'm 100% sure, that communication between View and ViewModel is correct, because displaying simple message doesn't make me troubles. Am I doing right binding in ListView?
A couple things:
First,
TextBlock Text="{Binding ElementDescriptions}"
doesn't make a lot of sense because ElementDescriptions is a collection. If you want to loop through all the ElementDescriptions in your List you should really be binding the ItemSource of the ListView to ElementDescriptions then accessing some text property of the ElementDescriptions class:
<ListView Grid.Column="0" Grid.Row="1" Margin="10,0,10,5" ItemsSource="{Binding MyCollection.ElementsElementDescriptions }">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding ElementDescriptions.SomeTextField}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Second, are you using INotifyPropertyChanged so the view knows to update? More info on that here: OnPropertyChanged with a List

Changing the data for a ComboBox in WPF

So I have a ComboBox with data in it and it works how they want:
<ComboBox Grid.Column="1" x:Name="MyComboBox" Margin="2, 0, 2, 0"
ItemsSource="{Binding Path=MySamples}" DisplayMemberPath="SampleName" SelectedValue="{Binding Path=MySample}"
SelectionChanged="OnComboBoxChanged" FontSize="11" FontFamily="Arial"/>
However, now they want the ItemsSource to be indexed. So it should be something like:
some #: SampleName
Is there an easy way to make this change just for the ComboBox drop down without changing the architecture? I cannot change the List itself since in other areas of the map, it's just the SampleName without the index. Thanks.
If your ItemsSource is a complex type:
public class MyClass
{
public int Index { get; set; }
public string Name { get; set; }
}
Then use the DisplayMemberPath property of the ComboBox to control what gets displayed. In this case you'd add:
DisplayMemberPath="SampleName"
to the ComboBox definition.
If instead you want to display both the index and name then you'll need to define an ItemTemplate for the ComboBox:
<ComboBox ....>
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Index}" />
<TextBlock Text=" : " />
<TextBlock Text="{Binding Name}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>

Setting the SelectedItem for ComboBox component in WPF

I have been defined some ComboBox element:
<ComboBox Height="27" Margin="124,0,30,116" Name="cbProductDefaultVatRate" VerticalAlignment="Bottom" ItemsSource="{Binding}">
<ComboBox.ItemTemplate>
<DataTemplate>
<Label Height="26" Content="{Binding Path=Value}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
and set the data source for component items of VatRate type:
private void ShowAllVatRates()
{
cbProductDefaultVatRate.Items.Clear();
cbProductDefaultVatRate.ItemsSource = new VatRateRepository().GetAll();
}
VatRate object has a property:
private Product SelectedProduct
{
get; set;
}
where is a product contains VatRate as well:
SelectedProduct.DefaultVatRate
How to set SelectedItem property of ComboBox to SelectedProduct.DefaultVatRate?
// does not work!!!
cbProductDefaultVatRate.SelectedItem = SelectedProduct.DefaultVatRate;
Thank you for answers!
You need to make sure that the actual object instance behind SelectedProduct.DefaultVatRate is the same instance as the one that is part of the list returned by new VatRateRepository().GetAll() or object.Equals() must return true for the two instances.
Are you looking to get a TwoWay binding like this?
<ComboBox Height="27" Margin="124,0,30,116" Name="cbProductDefaultVatRate" VerticalAlignment="Bottom"
ItemsSource="{Binding}"
SelectedItem="{Binding SelectedProduct.DefaultVatRate, Mode=TwoWay}>
<ComboBox.ItemTemplate>
<DataTemplate>
<Label Height="26" Content="{Binding Path=Value}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>

Categories

Resources