Different DataContext in ItemsControl - c#

My Code looks like this:
<ItemsControl ItemsSource="{Binding Path=MTMngRoot.MTManager.MTCollection}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBox Text="{Binding Path=Name}" ToolTip="Name" Controls:TextBoxHelper.Watermark="Name" Grid.Column="0"/>
<ComboBox SelectedItem="{Binding Path=DefaultCT}" Grid.Column="1">
<ComboBoxItem>Item 1</ComboBoxItem>
<ComboBoxItem>Item 2</ComboBoxItem>
</ComboBox>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
This code works correctly. But now I want to bind the Itemssource from the ComboBox. My Problem is now, the Path of the Items that should be bind to the ComboBox is completly different. The Path looks like this: CTMngRoot.CTManager.CTCollection.Name. Any ideas how I can do this?

You walk up to the control with the correct DataContext in these cases.
{Binding DataContext.CTMngRoot.CTManager.CTCollection,
RelativeSource={RelativeSource AncestorType=ItemsControl}}

Related

Cannot align textboxes inside grid properly among themselves

I have the following DataTemplate where inside is a Grid with a 'TextBlock' and TextBox that I want to align to the center:
<DataTemplate x:Key="OneSettingsEntryTemplate" DataType="{x:Type templateHelper:InputText}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0"
Style="{StaticResource StandardTextBlocksStyle}"
Text="{Binding Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<TextBox Grid.Column="1"
Style="{StaticResource DefaultTextBoxesStyle}"
Text="{Binding Content, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</Grid>
</DataTemplate>
In one of my UserControls I have the following code where I use the Template:
<StackPanel DataContext="{Binding ElementName=ControlForProjectSettings, Path=ViewModel}"
HorizontalAlignment="Center">
<TextBlock Style="{StaticResource HeadingTextBlocksStyle}"
Text="Project settings"/>
<ListView Background="#DAE7F5"
ItemsSource="{Binding ProjectSettingEntries}"
ItemTemplate="{StaticResource OneSettingsEntryTemplate}">
</ListView>
</StackPanel>
When I run my application and display some items, the last item has a longer text and therefore the TextBox flips to the right. Application Image
I tried playing around with the HorizontalAlignment and VerticalAlignment properties inside the Grid or also using a DockPanel instead of a Grid but couldn't find a solution. Any ideas?
Thanks to this source: WPF share column width between separate grids I solved my problem.
I added the IsSharedSizeScope to my Grid and the SharedSizeGroup property to my columns.
<Grid IsSharedSizeScope="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="A"/>
<ColumnDefinition Width="Auto" SharedSizeGroup="A"/>
</Grid.ColumnDefinitions>

Align controls correctly when using ItemsControl in WPF

Can someone tell me how to align and resize controls correctly when using the ItemsControl.
I want to have a description on the left and a TextBox on the right for multiple fields which are defined in an ObservableCollection to end up with something like:
First Name: [FirstNameTextBox]
Last Name: [LastNameTextBox]
Date of Birth: [DobTextBox]
but instead I'm getting this:
First Name: [FirstNameTextBox]
Last Name: [LastNameTextBox]
Date of Birth: [DobTextBox]
I want all the textbox to be aligned based on the largest <TextBlock>. If this was done directly in a <Grid> control, it would be straight forward as all controls are directly in the grid and you would just have the following columns definition defined
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
I thought I could use the SharedSizeGroup property in the <Grid> but it still doesn't resize correctly. Instead it only displays the <TextBlock> stretch across the <Grid>.
Here's my code:
<Grid Grid.IsSharedSizeScope="True" Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="Labels" />
<ColumnDefinition Width="*" SharedSizeGroup="InputControls" />
</Grid.ColumnDefinitions>
<ItemsControl Grid.Row="1" ItemsSource="{Binding SelectedTemplate.Fields}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="Labels"/>
<ColumnDefinition SharedSizeGroup="InputControls"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Path=Label}" Grid.Column="0" Margin="5"
VerticalAlignment="Center" Background="Red" />
<TextBox Text="{Binding Path=Value}" Grid.Column="1" Margin="5"
VerticalAlignment="Center" Background="Blue" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
Any idea how I can resolve this?
Thanks.
UPDATE1: I cannot get this to work as I need it to. This is what I've got so far:
<Grid Grid.Row="1" Background="Purple">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" SharedSizeGroup="Overall" />
</Grid.ColumnDefinitions>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="Labels" Width="Auto" />
<ColumnDefinition SharedSizeGroup="InputControls" Width="*" />
</Grid.ColumnDefinitions>
<ItemsControl ItemsSource="{Binding SelectedTemplate.Fields}"
Background="Yellow"
Grid.IsSharedSizeScope="True">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Background="Green">
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="Labels"/>
<ColumnDefinition SharedSizeGroup="InputControls"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Path=Label}"
Grid.Column="0"
Margin="5"
VerticalAlignment="Center"/>
<TextBox Text="{Binding Path=Name}"
Grid.Column="1"
Margin="5"
VerticalAlignment="Center"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
This ends up displaying my layout this way:
As you can see, my TextBox are correctly aligned based on the largest TextBlock but my ItemsControls is not stretched all the way across. I guess that makes sense as it is within the same grid where the ColumnDefinitions are defined.
Now, if I move the ColumnDefinitions' out this grid to the outer grid and remove all instances ofGrid.IsSharedSizeScope`, I guess the following:
Which once again is closer to what I need as my ItemsControl is now stretching all the way as I've set its Grid.ColumnSpan="2" and my TextBox are still aligned to the TextBlock and are stretching all the way across but the problem now is that the TextBlock should be smaller as the Column is set to Auto but they appear to behave as if the column was set to * and I guess I'm losing the purpose of using IsSharedSizeScope since it has been removed.
Now if I add IsSharedSizeScope="True" to the outer grid, I get the following result:
Again, this is close to what I want as my ItemsControl is stretched, my textboxes are also stretch but they are no longer aligned to the largest TextBlock.
Finally, if I add Grid.IsSharedSizeScope="True" to ItemsControl as originally suggested by #mm8,
<Grid Grid.Row="1" Background="Purple" Grid.IsSharedSizeScope="True">
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="Labels" Width="Auto" />
<ColumnDefinition SharedSizeGroup="InputControls" Width="*" />
</Grid.ColumnDefinitions>
<Grid Grid.ColumnSpan="2" >
<ItemsControl ItemsSource="{Binding SelectedTemplate.Fields}"
Background="Yellow"
Grid.IsSharedSizeScope="True">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Background="Green">
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="Labels"/>
<ColumnDefinition SharedSizeGroup="InputControls"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Path=Label}"
Grid.Column="0"
Margin="5"
VerticalAlignment="Center"/>
<TextBox Text="{Binding Path=Name}"
Grid.Column="1"
Margin="5"
VerticalAlignment="Center"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
<!--<TextBlock Text="Invoice Number" Grid.Column="0" Margin="5" VerticalAlignment="Center"/>
<TextBox Text="InvoiceNumber" Grid.Column="1" Margin="5" VerticalAlignment="Center"/>-->
</Grid>
I get the following:
Which brings me back to square one, though the definitions are different?
I need to achieve the following:
What am I doing wrong??
Thanks.
Try to set the Grid.IsSharedSizeScope property of the ItemsControl itself:
<ItemsControl Grid.Row="1" ItemsSource="{Binding SelectedBarcodeTemplate.Fields}"
Grid.IsSharedSizeScope="True">
Synchronizing the width of elements in an ItemsControl: https://joshsmithonwpf.wordpress.com/2008/09/06/synchronizing-the-width-of-elements-in-an-itemscontrol/
I eventually found the answer in the following article: WPF Tutorial - Grid Panel under the section: "How to share the width of a column over multiple grids".
As per article:
Columns and rows that participate in size-sharing do not respect Star sizing. In the size-sharing scenario, Star sizing is treated as Auto. Since TextWrapping on TextBlocks within an SharedSize column does not work you can exclude your last column from the shared size. This often helps to resolve the problem.
So my final XAML looks like this:
<Grid Grid.Row="1" Background="Purple" >
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="Labels" Width="Auto" />
<ColumnDefinition SharedSizeGroup="InputControls" Width="*" />
</Grid.ColumnDefinitions>
</Grid>
<ItemsControl ItemsSource="{Binding SelectedBarcodeTemplate.Fields}"
Background="Yellow"
Grid.IsSharedSizeScope="True">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Background="Green" ShowGridLines="True">
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="Labels"/>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Path=Label}"
Grid.Column="0"
Margin="5"
VerticalAlignment="Center"/>
<TextBox Text="{Binding Path=Name}"
Grid.Column="1"
Margin="5"
VerticalAlignment="Center"
HorizontalAlignment="Stretch"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
And the outcome now finally looks correct:
Hope this helps others!

Display multiple column data in C# WPF

I need to display two columns of dataset; first column is the Checkbox items and second column would be just a list<string>
I am able to build first column (grid.column=0) using Listbox with Checkbox in XAML as:
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<ListBox x:Name="Listitems" Grid.Column="0" SelectionMode="Multiple" ItemsSource="{Binding MonthlyResults}" >
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding logdate}" IsChecked="{Binding Checked ,Mode=TwoWay}"
Click="CheckBox_Click"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
User interface is displayed correctly as:
For the second column, I thought of using a ListView(grid.colum=1) and updated the above XAML as:
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<ListBox x:Name="Listitems" Grid.Column="0" SelectionMode="Multiple" ItemsSource="{Binding MonthlyResults}" >
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding logdate}" IsChecked="{Binding Checked ,Mode=TwoWay}"
Click="CheckBox_Click"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<ListView Grid.Column="1" Name="CatNames" FontSize="13" SelectionMode="Extended"
ItemsSource="{Binding Path=OFMCategoriesNames}" IsSynchronizedWithCurrentItem="False" >
</ListView>
</Grid>
But the user interface is messed up. Both columns have their own scrollbars.
How to display the columns in the same listbox ?
*************Update based on the answer provided***************
I updated the XAML as:
<Grid Grid.Row="0">
<ListBox x:Name="Listitems" SelectionMode="Multiple" ItemsSource="{Binding MonthlyResults}" >
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" SharedSizeGroup="A1"/>
<ColumnDefinition Width="*" SharedSizeGroup="A2"/>
</Grid.ColumnDefinitions>
<CheckBox Grid.Column="0" Content="{Binding logdate}" IsChecked="{Binding Checked ,Mode=TwoWay}" Click="CheckBox_Click"/>
<ListView Grid.Column="1" Name="CatNames" FontSize="13" SelectionMode="Extended"
ItemsSource="{Binding MeasureMethod}" IsSynchronizedWithCurrentItem="False" >
</ListView>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
Even after adding "sharedsizegroup", the columns are not aligned properly..
You can either use a Grid view inside the ListView like
<ListView.View>
<GridView>
....
</GridView>
</ListView.View>
or you can use a grid inside your template
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Grid.IsSharedSizeScope="True">
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="A"/>
<ColumnDefinition SharedSizeGroup="B"/>
<ColumnDefinition SharedSizeGroup="C"/>
</Grid.ColumnDefinitions>
<CheckBox Grid.Column="0"/>
<TextBlock Grid.Column="1"/>
<TextBlock Grid.Column="2"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>

Template selector within data template uwp

I have a listview with a ItemTemplateSelector to load my custom datatemplate based on a model. I'd like to know if i can use another TemplateSelector inside the main DataTemplate to load another Datatemplate to change the listview item DataTemplate based on the same model.
Main ListView
<ListView
Padding="10"
Grid.Row="1"
ItemsSource="{Binding DbObjectList, Mode=TwoWay}"
IsItemClickEnabled="True"
ItemTemplateSelector="{StaticResource TemplateSelector}"
x:Name="Comps">
Main DataTemplate
<DataTemplate x:Key="SetupDataTemplate" x:DataType="data:Setup">
<Grid HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{x:Bind text}" HorizontalAlignment="Stretch" FontSize="16" />
<ContentControl Grid.Column="1" Content="{Binding}" ContentTemplateSelector="{StaticResource SetupTemplateSelector}" />
<TextBlock Grid.Column="2" Text="{x:Bind key}" HorizontalAlignment="Stretch" FontSize="16" />
</Grid>
</DataTemplate>
I tried to use ContentControl/ContentPresenter to load the DataTemplate i want, but the Content property is always NULL.
<ContentControl Grid.Column="1" Content="{Binding}" ContentTemplateSelector="{StaticResource SetupTemplateSelector}" />
SetupTemplateSelector
protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
{
.....
}
I need to pass the Listview item to SetupTemplateSelector to choose my DataTemplate.
Is it the right way to do that?
Are there better solutions to solve my problem?
If you need more just ask!
Thanks

Listbox of comboboxes and binding them WPF

I have a situation where i have a listbox of comboboxes , mainly it binds to a bridge entity so the object contains foreign keys . What i need to do is that i need to bind the display of the combos to the respective entities and their value members to the foreign key values in the bridge entity that i bind the listbox to.
the code i have now is :
<ListBox Name="lstServices" ScrollViewer.HorizontalScrollBarVisibility="Disabled" HorizontalContentAlignment="Stretch">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="2" DataContext="{Binding ElementName=wndMain,Path=DataContext}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<ComboBox Name="cmbService" SelectedIndex="0" DisplayMemberPath="Name" SelectedValuePath="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=FK_ServiceID}" ItemsSource="{Binding Path=AllServices}" Grid.Column="0"></ComboBox>
<ComboBox Name="cmbService_Role" Margin="2,0,0,0" SelectedValuePath="{Binding Path=FK_ServiceRoleID}" DisplayMemberPath="Name" ItemsSource="{Binding Path=AllService_Roles}" Grid.Column="1"></ComboBox>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I could manage to display the values that i needed but since the List Item context changed i can't get to the listbox itemSource .
Any help is appreciated
Bishoy
I got it :D , here is how it should go
<ListBox Name="lstServices" ScrollViewer.HorizontalScrollBarVisibility="Disabled" HorizontalContentAlignment="Stretch" ItemsSource="{Binding MemberServices}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ComboBox Name="cmbService" SelectedValue="{Binding FK_ServiceID,Mode=TwoWay}" ItemsSource="{Binding ElementName=wndMain, Path=DataContext.AllServices,Mode=OneTime}" SelectedValuePath="ID" DisplayMemberPath="Name" Grid.Column="0" ></ComboBox>
<ComboBox Name="cmbService_Role" SelectedValue="{Binding FK_ServiceRoleID,Mode=TwoWay}" ItemsSource="{Binding ElementName=wndMain, Path=DataContext.AllService_Roles,Mode=OneTime}" SelectedValuePath="ID" DisplayMemberPath="Name" Grid.Column="1" Margin="2,0,0,0"></ComboBox>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>

Categories

Resources