ComboBox items with a binded value - wpf

In my WPF page I would like to create a ComboBox with first item empty and the second one binded with a property value, so I did:
<DataGrid x:Name="grdTmplBit" ColumnWidth="*" Style="{StaticResource DataGridStyle}" EnableColumnVirtualization="True" CanUserSortColumns="true" Margin="4,3,2,7" MaxHeight="930" SelectionMode="Extended" SelectionUnit="FullRow" ItemsSource="{Binding ElementName=ObjectsTree, Path=SelectedItem.InfosView, IsAsync=True}" >
<DataGrid.Columns>
<DataGridTemplateColumn Width="110" Header="COMM" Visibility="Visibile">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox Width="90" SelectedValue="{Binding Comm.UnitName, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource workModeStyle}" SelectedValuePath="Content">
<ComboBoxItem Content="" />
<ComboBoxItem Content="{Binding Comm.UnitName}" />
</ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
The property UnitName is a string. Please consider that the ComboBox is inside a DataGridTemplateColumn. Basically the second item is always empty and if I change the ComboBox with a TextBox the value are shown correctly. Any help?

I think your issue is that you bind the SelectedValue to Comm.UnitName and you also bind the second ComboBoxItem content to this property. This means the ComboBox will act in one of these ways:
(Initial selected value is from Comm.UnitName) > The selected line shows this item> You select the empty item > The Comm.UnitName will get set to the empty string > Result: Both ComboBoxItems are empty (one is set as empty, the other is synchronized with Comm.UnitName, which is empty now, too)
(Initial selected value is the first item, empty) > The selected line shows this item > The Comm.UnitName will get set to the empty string > Result: The same as above.
In order to solve this issue, you could consider one of these options:
Create a dedicated property for the SelectedValue, so the Comm.UnitName does not get overwritten.
Create a dedicated property for the value in the ComboBoxItem.
Use a OneTime mode binding to only synchronize the initial value (this does not work for all cases, especially not if you save the empty value in Comm.UnitName, same issue).
<ComboBoxItem Content="{Binding Comm.UnitName, Mode=OneTime}" />

Related

Single-click-editable bound CheckBox in Xceed DataGridControl

I've spent the past hour searching for solutions to what should be a simple problem: how to create a single-click-editable bound CheckBox in Xceed's community DataGridControl.
To be clear: I want a CheckBox column where the user may click any CheckBox, regardless of what row is selected, and have the view model's IsSelected property changing accordingly.
Below is the latest permutation I've tried. This code reads the value from the model, but clicking the CheckBox does not call the IsSelected setter for some reason.
<xcdg:DataGridControl x:Name="DictionariesDataGridControl" ItemsSource="{Binding Mode=OneWay, Source={StaticResource DictionariesViewSource}}" AutoCreateColumns="False" AutoRemoveColumnsAndDetailConfigurations="False" SelectionMode="Extended" NavigationBehavior="RowOnly">
<xcdg:DataGridControl.View>
<xcdg:TableView UseDefaultHeadersFooters="False" ShowRowSelectorPane="False" VerticalGridLineThickness="0">
<xcdg:TableView.FixedHeaders>
<DataTemplate>
<xcdg:ColumnManagerRow BorderThickness="0"/>
</DataTemplate>
</xcdg:TableView.FixedHeaders>
</xcdg:TableView>
</xcdg:DataGridControl.View>
<xcdg:DataGridControl.Columns>
<xcdg:Column FieldName="IsSelected" MinWidth="20" MaxWidth="20" CellEditorDisplayConditions="RowIsCurrent">
<xcdg:Column.CellContentTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding ., Mode=OneWay}" IsHitTestVisible="False"/>
</DataTemplate>
</xcdg:Column.CellContentTemplate>
<xcdg:Column.CellEditor>
<xcdg:CellEditor>
<xcdg:CellEditor.EditTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding ., Mode=TwoWay}"/>
</DataTemplate>
</xcdg:CellEditor.EditTemplate>
</xcdg:CellEditor>
</xcdg:Column.CellEditor>
</xcdg:Column>
</xcdg:DataGridControl.Columns>
EDIT 1
I'm trying this, which does exactly what I need:
<xcdg:Column FieldName="IsSelected" MinWidth="20" MaxWidth="20" CellEditorDisplayConditions="Always"/>
except that, for some reason, the CheckBox is styled with a blue background!
I've selected the element in the visual tree that has a Background property defined as SolidColorBrush with #FF0000FF as the color:
EDIT 2
I decompiled the DataGridCheckBox class that Xceed uses to render the CheckBox and found this override:
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
this.ChildCheckBox.Background = (Brush) new SolidColorBrush(Colors.Blue);
}
What a bizarre decision by Xceed to arbitrarily set the background color to blue.
EDIT 3
Using #JBrooks' answer, I tried the following:
<xcdg:Column FieldName="IsSelected" MinWidth="20" MaxWidth="20" CellEditorDisplayConditions="Always">
<xcdg:Column.CellEditor>
<xcdg:CellEditor>
<xcdg:CellEditor.EditTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding ., Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</xcdg:CellEditor.EditTemplate>
</xcdg:CellEditor>
</xcdg:Column.CellEditor>
</xcdg:Column>
Unfortunately, for some reason the setter on the IsSelected property is never called when I check the box. The getter is called several times, though, and the CheckBoxes are appearing correctly on initial bind.
You have both a CellContentTemplate and a CellEditor, so the first click does the "go into edit mode" logic. Just have a single one like below. This is for a normal WPF DataGrid, but maybe you can try something similar for your grid.
<DataGridTemplateColumn Header="Active" SortMemberPath="IsActive" >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding IsActive, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" IsEnabled="{Binding IsEnabled}" Style="{StaticResource rightsCB}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
For this DataGrid I also have these properties set:
SelectedItem="{Binding SelectedUser, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
SelectionUnit="FullRow" SelectionMode="Single"
So this DataGrid does act like what you want - I click the checkbox in row 4 and the IsChecked changes and it also makes row 4 the current row which sets the SelectedUser to the user bound to row 4.

WPF DataGrid Radio Button Binding Issue

I am having RadioButton binding issue.Below is my xaml code.
<Grid Style="{DynamicResource MainFrameGrid1}">
<Grid Name="grdPCM">
<DataGrid AutoGenerateColumns="False" Height="407" HorizontalAlignment="Left" Margin="18,102,0,0" Name="dgMI" VerticalAlignment="Top" Width="781"
CanUserAddRows="False" CanUserDeleteRows="False" CanUserReorderColumns="False" CanUserResizeColumns="True" CanUserSortColumns="False" SelectionMode="Single"
SelectionUnit="Cell" EnableColumnVirtualization="True">
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<RadioButton Name="rbM" GroupName="CMGrp" IsChecked="{Binding Path=SELECT, Mode=TwoWay}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Grid>
In code behind I am doing like this.
I am getting data from the database and storing it in the DataTable "dtMIData".Then I am temporarily adding a boolean column called "SELECT" and assigning it to data grid like below in code behind.
DataColumn dcRB = new DataColumn("SELECT");
dcRB.DataType = Type.GetType("System.Boolean");
dcRB.DefaultValue = false;
dtMIData.Columns.Add(dcRB);
dtMIData.AcceptChanges();
dgMI.ItemsSource = dtMIData.AsDataView();
I am binding this new column "SELECT" with the RadioButton control.I want to select only one record,out of multiple retrieved records and want to retrieve the selected record in the code behind based on the "SELECT" column value.i.e."SELECT" column value is true.But even though RadioButton is checked,required binding column "SELECT" is not updating with value true.How to reflect the checked state in the related binding column?
In a DataGrid the bindings do not get updated until you end editing of the row. Try adding UpdateSourceTrigger=PropertyChanged to the RadioButton's binding expression to update bindings immediately:
<RadioButton Name="rbM" GroupName="CMGrp" IsChecked="{Binding Path=SELECT, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />

WPF DataGrid ItemsSource - Change from ComboBox

Here is a snippet of XAML:
<ComboBox ItemsSource="{Binding UnileverDataSet.Tables, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" Margin="5" x:Name="TableNameComboBox">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding TableName}"></TextBlock>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<DataGrid Margin="5" AutoGenerateColumns="True" ItemsSource="{Binding UnileverDataSet.Tables[TableNameComboBox.SelectedIndex]}"
UnileverDataSet is a DataSet made up of about 12 DataTables
The idea here is that when the ComboBox value changes, the DataGrid should update based on the index value from the ComboBox.
Is this possible or should I look at another way of doing this?
If I do: UnileverDataSet.Tables[0], then all works and data displays correctly.
You can do element binding with combobox..
Your combox will display list of items in the "UnileverDataSet.Tables" collection. When ever your select a item in Combo box the selected item will bounded to the Datagrid Items source (since we are using element binding)
Here is the sample code
<DataGrid Margin="5" AutoGenerateColumns="True" ItemsSource="{Binding SelectedItem,ElementName=TableNameComboBox}">

Silverlight ComboBox SelectionChanged event fires twice

I'm using a ComboBox within a DataGrid. I am using this DataGrid for both "Add" and "Edit". When I change the value of ComboBox in code during "Edit", the SelectionChanged Event gets fired twice. 1st time it assigns the proper value, then 2nd time null is assigned to ComboBox which clears the data I had set previously!!
I can't figure out what exactly I'm doing wrong.
Here's the XAML snippet where I bind the ComboBox to model.
<sdk:DataGridTextColumn x:Name="SlNo" Binding="{Binding SlNo}" Header="sl.no" IsReadOnly="True"/>
<sdk:DataGridTemplateColumn Header="Activity Type">
<sdk:DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox x:Name="ActivityTypeCombo" IsDropDownOpen="True"
ItemsSource="{Binding AvailableActivityTypes}"
SelectionChanged="ActivityTypeSelectionChanged"
SelectedItem="{Binding SelectedActivityType, Mode=TwoWay}"
SelectedValue="{Binding Path=Description, Mode=TwoWay}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Description}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</DataTemplate>
</sdk:DataGridTemplateColumn.CellEditingTemplate>
</sdk:DataGridTemplateColumn>
The Code Snippet where I set the value is:
foreach (var claimDetailViewModel in Claims)
{
claimDetailViewModel.SelectedActivityType =
_autoFillModel.ActivityTypes.SingleOrDefault(at => at.Id == climDetailViewModel.ActivityTypeId);
}
ClaimDetailsGrid.ItemsSource = Claims;
It seems to me that using both SelectedItem and SelectedValue to control selection will not work properly.
When SelectedItem is set this will most likely trigger SelectedValue to be evaluated, and because there is no SelectedValuePath set it will result in SelectedItem=null.
Try removing the SelectedValue binding.

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.

Resources