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>
Related
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;}
}
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>
I have a setup like this:
ViewModel snippet:
private ObservableCollection<Field> _Fields;
public ObservableCollection<Field> Fields
{
get
{
return _Fields;
}
set
{
NotifyPropertyChanged(ref _Fields, value, "Fields");
}
}
private Field _SelectedField;
public Field SelectedField
{
get
{
return _SelectedField;
}
set
{
NotifyPropertyChanged(ref _SelectedField, value, "SelectedField");
}
}
XAML:
<ListBox x:Name="FieldList" ItemsSource="{Binding Fields}" SelectedValue="{Binding SelectedField}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I update the field collection quite frequently, like this:
List<Field> myFieldList = myDataSource.GetFields();
Fields = new ObservableCollection<Field>(myFieldList);
When I do this, the list box automatically defaults to selecting the first item. I would like it to not select anything by default (e.g. SelectedIndex = -1 or SelectedValue = null). How can I achieve this?
I tried it but could not reproduce it.
If you already have SelectedField in your VM try to set it tu null just after you update Fields.
You could also try to use an Action/Trigger to set the SelectedIndex to -1 like this
<ListBox x:Name="FieldList" ItemsSource="{Binding Fields}" SelectedValue="{Binding SelectedField}">
<i:Interaction.Triggers>
<ei:PropertyChangedTrigger Binding="{Binding Fields}">
<ei:ChangePropertyAction TargetObject="{Binding ElementName=FieldList}" PropertyName="SelectedIndex" Value="-1"/>
</ei:PropertyChangedTrigger>
</i:Interaction.Triggers>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
But actually it is not the best way to reset the selection.
After binding or loading the list, set
listbox1.SelectedIndex=-1;
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>
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>