How to always show combobox in data grid - wpf

WPF Application
In datagrid,if I use DataGridComboBoxColumn to show Combobox,it is only show when I double click the cell enter edit status.
I want to show the combobox all the timeļ¼Œ and don't need to double click the cell.
How to do?

Replace the DataGridComboBoxColumn with a DataGridTemplateColumn and add a ComboBox to its CellTemplate and CellEditingTemplate:
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="..." />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox ItemsSource="..." />
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>

Related

Getting selected item from Datagrid Combobox Cell

I've been trying to get a selected item from a combobox in a datagrid cell. I have an datagrid which contains several comboboxes which are bound with ObservableCollection. So, the code in my WPF look like this:
<DataGrid x:Name="DgvEmployee" ItemsSource="{Binding}">
<DataGrid.Columns>
<DataGridTemplateColumn Header="Name" Width="*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox x:Name="cboxName" ItemsSource="{Binding EmployeeName}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Department" Width="*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding EmployeeDept}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
And in my Class:
Dim comboBoxLoad As New ObservableCollection(Of ClcomboboxBinding)
comboBoxLoad.Add(New ClcomboboxEmployee)
DataContext = comboBoxLoad
My Class ClcomboboxEmployee populates EmployeeName and EmployeeDept from DB. So, it's working fine. Now I want to save from the comboboxes depending what user select. Now,
How can I get the selected item from each combobox and save in a Class(dummyClass) object String(SelectedEmployeeName, SelectedEmployeeDept).
I've tried something like this after searching for right solution what I really want, most of the solutions are for datagridview, not datagrid:
Dim seletedCB = DgvEmployee.Columns(1).GetCellContent(DgvEmployee.Items(0)) MsgBox(seletedCB.ToString())
But it's giving me output as System.Windows.Controls.ContentPresenter.
I also have checked with debugging selectedCB doesn't contain selecteditem. What am I doing wrong? How can I achieve the selected item?
I am really stuck here. Your contribution would be life saving. Thanks a lot in advance.

Update items in ComboBox after lookup value is added

I have a WPF form that contains a DataGrid. This DataGrid is editable. One column of the DataGrid contains a ComboBox with a list of lookup codes for the user to select from.
While editing, the user can add a new lookup code by calling a modal window. When control is returned to the DataGrid, the combobox does not have the new lookupcode.
How can I refresh the list in the combobox after an item is added?
Here is how my combobox is defined. Below is the column of the DataGrid and then my dictionary snippet.
<DataGridTemplateColumn Header="Type" Width="160">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding AddrType.Description}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<ComboBox Name="cboAddrtype"
ItemsSource="{Binding Source={StaticResource addrTypeList}}"
SelectedValuePath="ID"
DisplayMemberPath="Description"
SelectedValue="{Binding AddrTypeID, UpdateSourceTrigger=PropertyChanged}"
Width="100" />
<Button ToolTip="New" Name="btnNewAddressType" Click="btnNewAddressType_Click">
<Image Source="Images\Add.png" Style="{StaticResource buttonImageStyle}" />
</Button>
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
The method GetAddressTypes() returns an ObservableCollection.
<ObjectDataProvider x:Key="addrTypeList" IsAsynchronous="True"
MethodName="GetAddressTypes"
ObjectType="{x:Type components:AddressComponent}"/>
I would add the new address to the addrtypeList when the modal window is closed, or the object saved depending on your desired behavior. Because its an observableCollection it should update the combo box automatically.

Custom WPF usercontrol within a datagrid cell - How does this child control get the row object or Id on an event?

So I have a custom control:
<Grid>
<StackPanel HorizontalAlignment="Center" Orientation="Vertical">
<CheckBox x:Name="chkboxListen" HorizontalAlignment="Center" Checked="chkboxListen_Checked" Unchecked="chkboxListen_Unchecked"/>
<MediaElement x:Name="mediaElementAudioPlayer" Volume="{Binding ElementName=sliderVol, Path=Value}" />
</StackPanel>
</Grid>
And it will reside within a DataGrid Template Column:
<DataGridTemplateColumn x:Name="callListenL" Header="Listen(L)" IsReadOnly="False">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<localControls:AudioPlay x:Name="audioPlayL" localControls:AudioPlay>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
My question is:
When I Check the chkboxListen CheckBox, how I can get the Information from the row of the DataGrid (Parent)? Each row has a myObject with an Id. I just need that Id.
Thank you in advance.
You can expose a property from within your user control and set the value of that property when the datagrid data binds.
For example, say your user control's property is called ParentRowId you could set it in code behind or use an Eval expression
<DataGridTemplateColumn x:Name="callListenL" Header="Listen(L)" IsReadOnly="False">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<localControls:AudioPlay x:Name="audioPlayL" ParentRowId='<%# Cint(Eval("Id")) %>' localControls:AudioPlay>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

WPF datagrid - enable selecting, disabling text input

I have a C# WPF Datagrid, with a checkbox column, hyperlink columns and text columns.
My DataGrid is bound to a DataTable. The columns are not auto generated, but I do create them in code dynamically, since the number of columns is not known in advance.
I would like to enable the text in the cells to be selected (for ctrl+c purpose) but yet disable editing. I don't want the text to be changed.
Anyone can help?
One possibility is probably be to use a DataGridTemplateColumn:
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBox IsReadOnly="True" Text="{Binding YourProperty,Mode=OneWay}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
This works also with Checkboxes, add a CheckBox, Bind its IsChecked and use as the content a TextBox that is set to IsReadOnly.
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding YourBooleanValue}">
<TextBox IsReadOnly="True" Text="YourCopyableTextOrABindingToText"/>
</CheckBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
If you want to have the checkbox readonly, set its Enabled-property to false. However in this case, you have to declare the TextBox not as a child but as a sibling of the CheckBox (use a grid or a StackPanel) for this.
If you want to make data readonly for the whole DataGrid, use:
<DataGrid IsReadOnly="True">
THis is also possible for columns:
<DataGridTextColumn IsReadOnly="True">
If you want to define it per row, you have to use DataGridTemplateColumns and bind the IsReadOnly-proeprty of the edit-control.
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBox IsReadOnly="{Binind YourReadOnlyProperty}" Text="{Binding YourProperty,Mode=OneWay}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
If your users usually copy an entire cell at once you can set the DataGrid's SelectionUnit to Cell
If they copy sections of a cell you're better off overwriting the CellTemplate to display a Label as HCL recommended
I'm fairly sure that if you set the DataGridTextBoxColumn's IsReadOnly property to true, you'll still be able to select and copy the contents.

binding combox in wpf datagrid

I have a list that I populate in the init of my viewmodel:
ListOfEmployees = new List<EmployeeBO>(employeeRepository.GetEmployees(true, true));
I am trying to get a combobox in a datagrid to populate from this list.
<DataGridTemplateColumn Header="U/M" MinWidth="145">
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox Name="cboUnitMeasure"
ItemsSource="{Binding Path=ListOfUnitMeasures}"
DisplayMemberPath="UnitMeasureDescription" SelectedValuePath="UnitMeasureValue"
SelectedValue="{Binding UnitMeasureValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
HorizontalAlignment="Left" Width="140" />
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding UnitMeasureDescription}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
When the dg loads, the cell template displays the UnitMeasureDescription value, but when I click on the cell to edit, there are no items in the combobox. On the other hand, when I use a static resource from an xml file as the itemsource-using the same property names-the combobox contains the items:
<DataGridTemplateColumn Header="U/M" MinWidth="145">
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox Name="cboUnitMeasure"
ItemsSource="{Binding Source={StaticResource UnitMeasureData}}"
DisplayMemberPath="UnitMeasureDescription" SelectedValuePath="UnitMeasureValue"
SelectedValue="{Binding UnitMeasureValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
HorizontalAlignment="Left" Width="140" />
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding UnitMeasureDescription}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
I put a breakpoint just after populating ListOfEmployees in my vm and it contains items. I also verified the property names in the DisplayMemberPath and SelectedValuePath are correct. Not sure what I am doing wrong here.
Is "ListOfUnitMeasures" a property on the VM or a property of an EmployeeBO? Ok, assuming that the DataGrid's ItemsSource is set to the List<EmployeeBO> and that there's another list on the VM called "ListUnitOfMeasures", here's my explanation:
The DataContext of each row in the DataGrid will be equal to the elements in the DataGrid's ItemsSource. In your case, each row will use an EmployeeBO as its DataContext. And since the "ListOfUnitMeasures" isn't a property of Employee BO, the Binding on the ComboBox will not work and thus won't display anything.
One possible solution is change the Binding on your ComboBox to use a RelativeSource pointing back to the parent DataGrid as follows:
<ComboBox Name="cboUnitMeasure"
ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=DataContext.ListOfUnitMeasures}"/>

Resources