Reputation: 3413
I'd like to have a list of TextBlocks with ComboBoxes next to each of them. The data source of ComboBoxes should be the same for every ComboBox. Each TextBlock however should contain sequent element of List Both data source for ComboBoxs and TextBlocks are in my "settings" object. So I set DataContext of the whole window to this settings object.
Here's my problem: Data source of TextBlock is: List called Fields, which is inside of an object called "Header" of type "Line" (which is of course inside settings object, which is my datacontext).
So, graphically: settings(type: Settings) - Header(type: CsvLine) - Fields(type: List of string)
Now ComboBox. Data source of every ComboBox should be a List called Tags
Graphically: settings(type: Settings) - Tags(type: List of string)
I don't know how I should point to these locations, I tried a lot of options, but none of them work. I see just a blank window.
Here's my code:
<Grid>
<StackPanel Orientation="Horizontal">
<ItemsControl ItemsSource="{Binding Headers}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Fields}"/>
<ComboBox ItemsSource="{Binding DataContext.Tags,
RelativeSource={RelativeSource AncestorType=ItemsControl}}">
</ComboBox>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Grid>
I have no idea what I should actually pass as ItemsSource to ItemsControl, because I think it should be common source for both TextBoxes and ComboBoxes, but their only common source is settings object - but i already set it as my DataContext. I have used RelativeSource in ComboBox, but I'm not really sure what it's used for (although I read an article about it on MSDN). I don't know why but it's really hard for me to understand binding - I'm struggling to get anything working.
//EDIT: Here's my Settings class - which is the type of my settings object:
public class Settings
{
public CsvLine AllHeaders1
{
get
{
return _allHeaders1;
}
}
public CsvLine _allHeaders1 = new CsvLine()
{
Fields = new List<string>()
{
"Header1" , "Header2" , "Header3"
}
};
private List<String> _tags;
public List<String> Tags
{
get
{
return new List<string>() { "Tag1", "Tag2", "Tag3", "Tag4", "Tag5" };
}
set
{
_tags = value;
}
}
}
And here's my CsvLine class:
public class CsvLine
{
public List<string> Fields = new List<string>();
public int LineNumber;
}
Upvotes: 2
Views: 6692
Reputation: 1993
So, I'm not 100% sure of what it is you want, but the following should get you started.
Firstly, you need to ensure you bind to public properties - not public members - so the CsvLine.Fields member needs to be changed to public List<string> Fields { get { return _fields; } set { _fields = value; } }
. Also not that, if you want changes in the settings object to be reflected in the UI, you will need to implement INotifyPropertyChanged.
Anyway, with this in place and assigned to the DataContext of the grid, the following will display a vertical list of text blocks (showing "Header 1", "Header 2", "Header 3") each with a combo box to the right containing the values "Tag1", "Tag2" ... "Tag5".
<Grid x:Name="SourceGrid">
<ItemsControl ItemsSource="{Binding Path=AllHeaders1.Fields}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding}" />
<ComboBox ItemsSource="{Binding ElementName=SourceGrid, Path=DataContext.Tags}" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
Hope it helps.
Upvotes: 3