Setting ComboBox.SelectedItem at bind time? - wpf

I have a ComboBox in a DataTemplate which is being selected by a cell template selector in a DataGrid.
How do I set the SelectedItem to zero when the ComboBox is bound to its ItemsSource? There's often just one item and I want it to appear immediately instead of having to be selected by the user.
My DataGrid column looks like this:
<DataGridTemplateColumn Header="Qty Avl">
<DataGridTemplateColumn.CellTemplateSelector>
<selectors:PartAvailableSelector StrTemplate="{StaticResource PartAvailableAtStrTemplate}">
<selectors:PartAvailableSelector.NetTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding AltLocations}"
DisplayMemberPath="Name"
SelectedItem="0"
/>
</DataTemplate>
</selectors:PartAvailableSelector.NetTemplate>
</selectors:PartAvailableSelector>
</DataGridTemplateColumn.CellTemplateSelector>
</DataGridTemplateColumn>
My selector has DataTemplate properties, just because it's easier. I inlined the NetTemplate template for this post. I normally have it in my window resources.

SelectedItem will the hold entire object from ItemsSource, to set the 0 item as selected you need to set SelectedIndex="0" or in ViewModel u need to bind SelectedItem="{Binding SLocation}" to AltLocations[0]
<ComboBox ItemsSource="{Binding AltLocations}"
DisplayMemberPath="Name"
SelectedIndex="0"
/>
Or
<ComboBox ItemsSource="{Binding AltLocations}"
DisplayMemberPath="Name"
SelectedItem="{Binding SLocation}"
/>
Vm
private Location sLocation
public Location SLocation
{
get { return sLocation; }
set
{
sLocation= value;
OnPropertyChanged(new PropertyChangedEventArgs("SLocation"));
}
}
//Ctor
SLocation=AltLocations[0];

Related

View does not update UIElement property

I have a MainView with TabControl, which is intended to display child Views, and a ComboBox to display some values
MainView has this XAML:
<TabControl ItemsSource="{Binding ViewModelsCollection, Mode=TwoWay}"
SelectedItem="{Binding ViewModelsSelectedItem, Mode=TwoWay}">
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock>
<TextBlock Text="{Binding Path=Title}"/>
</TextBlock>
</DataTemplate>
</TabControl.ItemTemplate>
</TabControl>
<ComboBox x:Name="cmbProfiles"
ItemsSource="{Binding Path=ProfileCollection}"
SelectedItem="{Binding Path=ProfileSelectedItem, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
DisplayMemberPath="Key">
</ComboBox>
Also, MainView has DataTemplates for child Views - to be used in the TabControl:
<Window.Resources>
<DataTemplate DataType="{x:Type vm:OrdersViewModel}">
<v:OrdersView/>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:ShippingViewModel}">
<v:ShippingView/>
</DataTemplate>
</Window.Resources>
ChildViews are created in MainViewModel:
ObservableCollection<ViewModelBase> collection = new ObservableCollection<ViewModelBase>();
collection.Add(new OrdersViewModel());
collection.Add(new ShippingViewModel());
this.ViewModelsCollection = collection;
Each ChildView has a button, which IsEnabled property should depend on MainView's cmbProfiles selection:
<Button IsEnabled="{Binding Path=BtnServiceSetupIsEnabled}"
Content="Next ...">
</Button>
Code in MainView to handle that:
IOrdersViewModel ordersViewModel = (IOrdersViewModel)this.ViewModelsCollection.Where(x => x.GetType().Equals(typeof(OrdersViewModel))).FirstOrDefault();
if (profileItem.Key == "Custom")
{
ordersViewModel.BtnServiceSetupIsEnabled = true;
}
else
{
ordersViewModel.BtnServiceSetupIsEnabled = false;
}
The problem occurs when I change selection in cmbProfiles: ChildViewModel.BtnServiceSetupIsEnabled gets updated in code indeed, but the ChildView doesn't reflect that change, button stays disabled.
It does work fine if I don't use DataTemplates and simply add <v:OrdersView/> to my MainView, not dynamically filling the TabControl.
How can I fix that - and to have my TabControl's TabItems created dynamically?

How to bind itemsource in combobox based on another combox items in wpf?

If i have items in one combobox are CFG_REG,INT_REG,ST_REG,CMD_REG(which are defined in enum), if i select item CFG_REG then i should display GCR,PCR,LCR,CR,GSR,PSR in another combobox similarly,if i select INT_REG i should display IE,IS like that,.. How do i do that?
<ComboBox Grid.Column="2"
Grid.Row="1"
SelectedIndex="{Binding CMDIndex, Mode=TwoWay}"
x:Name="Combobox1"
Margin="0,0,1,0"
VerticalAlignment="Top">
</ComboBox>
<ComboBox Grid.Column="3" IsTextSearchEnabled="True"
Grid.Row="1"
x:Name="combobox2"
ItemsSource="{Binding }"
SelectedItem="{Binding RegisterIndex,Mode=TwoWay}"
VerticalAlignment="Top" IsSynchronizedWithCurrentItem="True" DisplayMemberPath="Name"
Margin="0,0,1,0">
</ComboBox>
You should bind a collection of items (i.e. ICollection or Observable collection) in your view model/Code to the first Combo box's itemsSource. You can bind the 'SelectedItem' of the first combo box to a property in the code behind/view model and then in the setter of this property, you should filter out another Collection which will be bound to other Combo box. I hope you get the idea.
For example:
<ComboBox ItemsSource ={Binding Collection1} SelectedItem ={Binding SelectedItem} .../>
In the Code:
public ICollection Collection1 {get;set;}
public ICollection Collection2 {get;set;}
public string SelectedItem
{
get {..}
set{
SelectedItem = value;
ChangeSecondCollection(value);
}
public void ChangeSecondCollection(string value)
{
Collection2 = //Filter your second collection here.
}

WPF: ComboBoxes in ListBox and concurrency

I have code like this:
<ListBox ItemsSource="{Binding}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock>Some Other Stuff Here</TextBlock>
<ComboBox ItemsSource="{Binding}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
The problem is, every time the outside ListBox.SelectedItem gets changed, the ComboBoxes inside it would change their SelectedIndex to -1. Which means if I click "Some Other Stuff Here" (unless the ListBoxItem it is in is selected), all the comboboxes' selection get cleared.
How do I overcome this? Thx!
Presumably your combobox is bound to something like an ObservableCollection - try exposing an instance of ICollectionView instead:
class DataSource
{
// ...
public ObservableCollection<string> MyData { get; private set; }
public ICollectionView MyDataView
{
get
{
return CollectionViewSource.GetDefaultView(this.MyData);
}
}
}
You can then bind your combobox with:
<ComboBox ItemsSource="{Binding MyDataView}" IsSynchronizedWithCurrentItem="True" />
This means that the 'selected item' for each data source is stored in the ICollectionView object instead of within the combobox, which should mean that it is persisted when the ListBox SelectedItem changes

WPF DataGrid - How do I use cell and row validation with DataGridTemplateColumn

How do I use cell and row validation with DataGridTemplateColumn?
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding DataType}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox SelectedItem="{Binding DataType}" ItemsSource="{Binding Source={x:Static app:ApplicationConfiguration.DataTypes}, ValidatesOnDataErrors=True}"/>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
It's a bit of a guess, but it looks like you want to prevent certain items from being selected. The easiest way would be to remove them from the list, but you could do it using validation as follows.
If the selected item is invalid, throw an exception in the Setter in the ViewModel:
public object DataType
{
get { return dataType; }
set
{
if(valueNotAllowed(value))
throw new Exception(string.Format("{0} is not a valid selection", value.ToString());
dataType = value;
}
}
Then set the binding for SelectedItem to ValidateOnExceptions (note that in your question, you specified ValidatesOnErrors for the ItemsSource binding - wrong property on the wrong binding):
<ComboBox SelectedItem="{Binding Path=DataType, ValidatesOnExceptions=True}"
ItemsSource="{Binding Source={x:Static app:ApplicationConfiguration.DataTypes}}"/>

ComboBox Binding in WPF

I am not able to set the selected value of a combobox.
this is how i am doing.
ComboBox x:Name="cmbProjectStatus" ItemsSource="{Binding ItemListCollection}"
DisplayMemberPath="Name"
SelectedValuePath="ID"
SelectedValue="{Binding Path=ItemList.ID}"
SelectedItem="{Binding Path=ItemList}"
HorizontalAlignment="Stretch" VerticalAlignment="Center" />
I am using MVVM pattern in my project
Please Help...
but wait, your selected value is defined because you set selecteditem and selectedvaluepath ;)you don't have to set selectedvalue, andEDITItemList seted as SelectedItem exists in ItemListCollection
This should work
ComboBox x:Name="cmbProjectStatus" ItemsSource="{Binding ItemListCollection}"
DisplayMemberPath="Name"
SelectedValuePath="ID"
SelectedItem="{Binding Path=ItemList}"
HorizontalAlignment="Stretch" VerticalAlignment="Center" />
if you want to get it worked in your case just override Equals method in your Item class like this
public class Item
{
...
public override bool Equals(object obj)
{
Item i = (Item)obj;
if (i.ID == this.ID)
return true;
return base.Equals(obj);
}
...
}

Resources