I need to get the values from my ComboBoxes that reside in an ObservableCollection being iterated through by an ItemsControl. And I need to store them in a separate data structure, at least I think I do. Sounds pretty straightforward? I hope it is, I’ve been stuck on it all day.
Here’s my XAML:
<Window.Resources>
<Style x:Key="IVCell" TargetType="{x:Type ItemsControl}">
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Variable.Name}"/>
<ComboBox x:Name="IVValues" ItemsSource="{Binding Values}"
SelectedIndex="0"/>
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
...
<ItemsControl Name="IndependentVariables" Style="{StaticResource IVCell}" ItemsSource="{Binding IVCollection}"/>
where IVCollection is defined here, in my ViewModel:
public class MainViewModel : ViewModelBase
{
public ObservableCollection<ExternalClass> IVCollection { get; set; }
...
}
Before you ask what ExternalClass is, know that that is what contains Variable and Values.
Here’s the problem. I need to get the SelectedIndex of ComboBox (so I would be changing the current code SelectedIndex="0"). And if my ExternalClass were what needed to contain those SelectedIndex values, that would be easy, since I already have access to its fields (Variable and Value). But I need those int values in
public class MainViewModel : ViewModelBase
{
public ObservableCollection<int> SelectedIndices { get; set; }
...
}
or something like that. I had made a quick wrapper class to contain both SelectedIndices and IVCollection, but obviously that won’t work, because ItemsControl wants an ObservableCollection, not a class with two ObservableCollections.
And I guess the real meat of the question here (I could be wrong, that’s why I’m asking) is how do I access a property that’s outside of the scope of the Style/DataTemplate I’m currently in (e.g. IVCell)? I can do it in the code-behind with no problem, like so,
private void IVValues_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
for (var i = 0; i < IndependentVariables.Items.Count; i++)
{
var uiElement = IndependentVariables.ItemContainerGenerator.ContainerFromIndex(i);
var cBox = FindVisualChild<ComboBox>(uiElement); //Homebrew method
//cBox.SelectedIndex
}
}
but once again, I’m trying to stay MVVM friendly. I’ve even tried using event commands with MVVM Light, etc., but that merely postpones the problem. I need to solve it. Or circumvent it.
@sleiman and @Brandon
Neither of your answers were 100%, but they were very helpful nonetheless. I reached my solution using elements from both of your answers, so I hesitate to accept one over the other.
I used a combination of the wrapper class solution and the exposed property solution (along with a semi-unrelated but nonetheless necessary event-handling technique) to create the following:
and
This additional integration with my ViewModel allows me to call a function whenever my
selectionIndexchanges. Neat! And clean!The corresponding changes in the XAML MainView: