How to get the selected value from a WPF ComboBox DataTemplate - wpf

I want to find out how to get the selected value from a combobox column in a listview with a gridview view or even a datagrid.
The xaml will look like this:
<ListView Name="lstPicker" ItemsSource="{Binding}" SelectionMode="Single" Margin="6" >
<ListView.Resources>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListView.Resources>
<ListView.View>
<GridView x:Name="gridParams" ColumnHeaderContainerStyle="{StaticResource DialogueGridViewColumnHeader}" >
<GridViewColumn Header="Workflow Parameters" Width="Auto" DisplayMemberBinding="{Binding WorkflowParameterName}" />
<GridViewColumn Header="Profile Parameters" Width="Auto">
<GridViewColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding Path=ProfileParametersList}" DisplayMemberPath="ProfileParameterName" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
What I want to do is to save for each workflow parameter in the list a value from the profiles parameter combobox.
The list is binded to an Observable Collection with some workflow parameters that contains another Observable Collection named ProfileParametersList that contains some parameter profiles. So for each item in the mother collection i want a detail to be picked from the child Collection and handled afterwards.
I tried to get the rows and cast them to the Class type that i use but i am unable to see what was selected in the combobox as the whole DetailsList is there. Any help is apreciated
The datagrid version can look like this:
<DataGrid AutoGenerateColumns="False" ItemsSource="{Binding}" Name="dgPicker" CanUserAddRows="False" CanUserDeleteRows="False" >
<DataGrid.Columns>
<DataGridTextColumn Header="Workflow Parameters" Binding="{Binding WorkflowParameterName}" IsReadOnly="True" />
<DataGridTemplateColumn Header="Profile Parameters">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding ProfileParametersList}" DisplayMemberPath="ProfileParameterName" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>

Create a property SelectedProfileParameter in your class WorkFlowParameter and bind it to the SelectedItem of your combobox. This should work for you then -
<DataGridTemplateColumn Header="Profile Parameters">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding ProfileParametersList}" DisplayMemberPath="ProfileParameterName" SelectedItem="{Binding SelectedProfileParameter}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

Related

set Combobox ItemsSource BindingContext to ViewModel

I have a ListView, in which I placed some ComboBoxes as following :
<ListView x:Name="ListViewCategories" SelectedItem="{Binding SelectedCategory}" ItemsSource="{Binding ListCategoryPart}" SelectionChanged="ListViewCategories_SelectionChanged">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListView.ItemContainerStyle>
<ListView.View>
<GridView>
<GridViewColumn Header ="{x:Static p:Resources.Machine}" >
<GridViewColumn.CellTemplate>
<DataTemplate>
<ComboBox
ItemsSource="{Binding ListCutMachines}"
SelectedValuePath="ID"
SelectedValue="{Binding DefaultCutMachine, UpdateSourceTrigger=PropertyChanged}"
DisplayMemberPath="Name" Width="100"
/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
DefaultCutMachine is part of my object CategoryPart(Items listed in ListView).
But what I would like is take the Combobox ItemsSource not from my objects, but from my ViewModel.
How can I bind all my Items Comboboxes ItemsSource not from the Items, but from my ViewModel?(I read about "BindingContext", but don't find how to do it on a ComboBox ItemsSource)
Essentially, you want to create a binding that has a RelativeSource with the proper DataContext of your ViewModel.
Here is an example:
ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type ListView}}, Path=DataContext.ListCutMachines}"
I hope this helps.

Putting ComboBox in a one special row in ListView in WPF

How to put a Combobox to a special row of a listview (WPF, VB.net)?
There is a ListView that has two columns. The columns are "Parameter" and "Values". The second column has different types (such as numbers, strings and "Selectable values") and is editable. The "Selectable values" have to appear in a Combobox.
One of the ways that I think about, is conditional XAML tags (I don`t know if it is possible or not ?) .
I tried this code but it shows Combobox for all rows in listview :
<ListView x:Name="listView"
HorizontalAlignment="Left"
Height="237"
Margin="40,34,0,0"
VerticalAlignment="Top"
Width="447"
ItemsSource="{Binding Values}">
<ListView.View>
<GridView>
<GridViewColumn Header="Parameter"
DisplayMemberBinding="{Binding Path=LName}"
Width="100" />
<GridViewColumn Header="Value"
Width="150">
<GridViewColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=ListView}, Path=ItemsSource}"
Width="120">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Type}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
I only want to use Combobox for one row while the type of the rest of rows are double or string. How can I do this?

Treeview shows random extra space

I have a treeview in wpf that is showing some strange behavior (at least I think it's strange). I don't see anywhere I can attach an image but basically on some of the items it looks like it's double spaced or has an extra 3px or so margin and on some it looks like it's single spaced. Here is the XAML defining it:
<TreeView Margin="5,0,0,5" ItemsSource="{Binding SortedCategories}" HorizontalContentAlignment="Stretch">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type COBie:CategoryData}" ItemsSource="{Binding SortedTypes}">
<CheckBox IsChecked="{Binding AnyChecked, Mode=TwoWay}" Content="{Binding CategoryName}" IsEnabled="{Binding HasTypes}" />
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type COBie:InstanceData}">
<CheckBox IsChecked="{Binding isChecked, Mode=TwoWay}" Content="{Binding ElemID}" />
</DataTemplate>
<DataTemplate DataType="{x:Type COBie:TypeData}">
<TreeViewItem IsEnabled="{Binding HasInstances}" HorizontalContentAlignment="Stretch">
<TreeViewItem.Header>
<CheckBox IsChecked="{Binding isChecked, Mode=TwoWay}" Content="{Binding ElemName}" />
</TreeViewItem.Header>
<ListView ItemsSource="{Binding SortedInstances}">
<ListView.View>
<GridView>
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding isChecked, Mode=TwoWay}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="ID" DisplayMemberBinding="{Binding ElemID}" />
<GridViewColumn Header="Name" DisplayMemberBinding="{Binding ElemName}" />
<GridViewColumn Header="Mark" DisplayMemberBinding="{Binding Mark}" />
<GridViewColumn Header="Room" DisplayMemberBinding="{Binding RoomDisplay}" />
</GridView>
</ListView.View>
</ListView>
</TreeViewItem>
</DataTemplate>
</TreeView.Resources>
</TreeView>
The only other relevant style that would apply is:
<Style TargetType="TreeViewItem">
<Setter Property="IsExpanded" Value="{Binding IsExpanded}" />
</Style>
I don't see anywhere that defines a margin at all and even if it did all of the elements are of the same class so it should apply to all equally.
Anyone know what is going on?
I had the same issue, that there were seemingly random gaps.
After looking closer I found out that the gaps appeared around items, that have underscore(s) in the name.
If you put the string directly in the content property of the CheckBox and it contains underscores, the CheckBox will surround a TextBlock with a Control named AccessText, probably to support short cut keys (similar to underscores in Button's Content property).
Now for some reason the Margin of the Checkbox is set on the TextBlock perfectly fine, if there is no AccessText involved, but is not set on the TextBlock inside the AccessText. This way the TextBlock inside the AccessText will have default TextBlock Style, which in my case was with Margin=5.
I guess in your case it must be a closely related issue.

How to add a DataGrid to a DataGridTemplateColumn.CellTemplate

I need to add a DataGrid to a DataGridTempateColumn,so i did this, but it dosen't work correctly,I don't know if i really can add a DataGrid to a DataGridTempateColumn?
<datagrid>
....
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<DataGrid HeadersVisibility="None" AutoGenerateColumns="False" CanUserAddRows="True" ItemsSource="{Binding ProjectCollection}">
<DataGridTextColumn Binding="{Binding Spec.Rev}" Width="*"></DataGridTextColumn>
<DataGridTextColumn Binding="{Binding Spec}" Width="*"></DataGridTextColumn>
</DataGrid>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
...
</DataGrid>
EDited:
while the ProjectCollection is null,we can't see the dataGrid,as you see in row 2 in the picture!
I doubt this will work. You will get the InvalidOperationException - Items collection must be empty before using ItemsSource. since you are setting the ItemsSource for the innner Grid and at the same time you are adding childs to the DataGrid.
Add the columns to the Columns DP of your dataGrid like this and it will work as you desired -
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<DataGrid HeadersVisibility="None" AutoGenerateColumns="False"
CanUserAddRows="True" ItemsSource="{Binding ProjectCollection}">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Spec.Rev}" Width="*"/>
<DataGridTextColumn Binding="{Binding Spec}" Width="*"/>
</DataGrid.Columns>
</DataGrid>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
Instead of use DataGrid you can use ListView with view GridView.
<DataGridTemplateColumn Header="Complex Data">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ListView ItemsSource="{Binding ProjectCollection}">
<ListView.View>
<GridView>
<GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}" />
<GridViewColumn Header="Date" DisplayMemberBinding="{Binding Date}" />
</GridView>
</ListView.View>
</ListView>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

WPF Listview - binding a text column to a combobox column selected item

I have a Listview:
<ListView ItemsSource="{Binding FieldMap.SourceTargetFieldMap, Mode=Default}">
<ListView.View>
<GridView>
<GridViewColumn Header="Source Fields" CellTemplate="{StaticResource sourceFieldsTemplate}"/>
<GridViewColumn Header="Source Values" CellTemplate="{StaticResource =sourceValueTemplate}">
<GridViewColumn Header="Target Field" CellTemplate="{StaticResource targetFieldTemplate}"/>
</GridView>
</ListView.View>
</ListView>
And I also have cell data templates that these bind to:
<DataTemplate x:Key="sourceFieldsTemplate">
<ComboBox x:Name="cbSourceField" SelectedValue="{Binding Path=SourceField, Mode=TwoWay}" DisplayMemberPath="FieldName" ItemsSource="{Binding SourceFieldValues}" Width="120" />
</DataTemplate>
<DataTemplate x:Key="sourceValueTemplate">
<TextBox x:Name="tbSourceValue" Margin="5,0,0,0" DataContext="{Binding ElementName=cbSourceField, Path=SelectedItem}" Text="{Binding Path=FieldValue, Mode=TwoWay}" TextWrapping="Wrap" Width="115" />
</DataTemplate>
<DataTemplate x:Key="targetFieldTemplate">
<TextBox x:Name="tbTargetField" Margin="5,0,0,0" Text="{Binding Path=TargetField}" TextWrapping="Wrap" Width="155" IsReadOnly="True"/>
</DataTemplate>
What I want to do is, bind the Source Value textbox field to the selected item of the SourceFields combobox. So when an item is selected from the sourcefield combobox, a property from the selectedItem (which is actually a object with two properties - something like fieldname and value) populates the textbox.
Both controls are "hidden" within datatemplates and I am not sure how to populate one from the other??
Any ideas? Much appreciated!!
Matt
You could insert a ContentConteol where content is bound to selected item of your listview - then the datetemplate should take care of displaying - I would set readonly on the textbox since altering the text will have no effect.

Resources