data binding in wpf combo box in data grid - c#

I am having one problem related to ComboBox of DataGrid. Data is binding but it is not showing in the ComboBox after binding. My code is like below:
<my:DataGridTemplateColumn Header="UsgSrc">
<my:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox Name="cbUsgSrc"
ItemsSource="{Binding Source={StaticResource UsgSrcUOMS}}"
SelectedValue="{Binding Path=UsgSrc}"
SelectedValuePath="UtType"
DisplayMemberPath="UtType">
</ComboBox>
</DataTemplate>
</my:DataGridTemplateColumn.CellTemplate>
</my:DataGridTemplateColumn>
Code for static resource:
UsgSrcUOMS.ObjectDataProvider UsageSrcUOMS = null;
UsageSrcUOMS = (ObjectDataProvider)FindResource("UsgSrcUOMS");
UsageSrcUOMS.ObjectInstance = objUtView;
Microsoft.Windows.Controls.DataGridCell cell = obj.GetCell(dgMtrHdr, J, 11);
if (cell != null)
{
ContentPresenter panel = cell.Content as ContentPresenter;
if (panel != null)
{
ComboBox cmbUsUtilit = obj.GetVisualChild<ComboBox>(panel);
cmbUsUtilit.IsEnabled = true;
if(objUtView!=null)
cmbUsUtilit.ItemsSource = objUtView;cmbUsUtilit.SelectedIndex=2;
}
}
What is the reason for this. Please help me to solve my problem.

Have you tried to change the Binding to the StaticResource, something like that
<ComboBox Name="cbUsgSrc"
ItemsSource="{StaticResource UsgSrcUOMS}"
SelectedValue="{Binding Path=UsgSrc}"
SelectedValuePath="UtType"
DisplayMemberPath="UtType">
</ComboBox>

Related

Reset binding in code

I'm writing an application that is able to switch language using this.
I also have a combox with two features:
supply help text if no item is selected in combobox (see this)
items are selectable with checkboxes (see this)
My combobox looks like
<Grid>
<ComboBox x:Name="MyCB" SelectionChanged="OnCbObjectsSelectionChanged" ...>
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked="{Binding IsSelected}" Checked="OnCbObjectCheckBoxChecked" Unchecked="OnCbObjectCheckBoxChecked" Width="20" />
<TextBlock Text="{Binding Value}" Width="100" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<TextBlock Visibility="{Binding SelectedItem, ElementName=MyCB, Converter={StaticResource Null2Vis}}"
IsHitTestVisible="False"
VerticalAlignment="Center"
Name="tbObjects"
Text="{ns:Loc Var1}"
FontSize="20"
Foreground="Gray"/>
</Grid>
I temporary deactivated the converter with return Visibility.Visible; with no effect.
Whenever I check some checkboxes the combobox.Text property is set and the binding from ns:Loc is overriden. How can I set it again in code if all checkboxes are unchecked?
private void OnCbObjectCheckBoxChecked(object sender, RoutedEventArgs e)
{
StringBuilder sb = new StringBuilder();
foreach (var cbObject in MyCB.Items)
if (cbObject.IsSelected)
sb.AppendFormat("{0}, ", cbObject.Value);
tbObjects.Text = sb.ToString().Trim().TrimEnd(',');
if (tbObjects.Text == "")
{
Binding myBinding = new Binding();
myBinding.Source = TranslationSource.Instance["Var1"]; // <- this does not work :/
myBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
BindingOperations.SetBinding(tbObjects, TextBox.TextProperty, myBinding);
tbObjects.Foreground = new SolidColorBrush(Colors.Gray);
}
}
When all checkboxes are unchecked there is no text in the combobox.
What am I missing?
Edit: Added TextBox element to code
If I understand your code correctly to restore the localization binding you don't need to redefine the Binding - it should be sufficient to use LocExtension with proper argument, because it derives from Binding:
if (tbObjects.Text == "")
{
var myBinding = new LocExtension("Var1");
BindingOperations.SetBinding(tbObjects, TextBox.TextProperty, myBinding);
tbObjects.Foreground = new SolidColorBrush(Colors.Gray);
}
But if for some reason you still want to redefine the Binding, here's what it should look like:
if (tbObjects.Text == "")
{
Binding myBinding = new Binding("[Var1]");
myBinding.Source = TranslationSource.Instance;
myBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
BindingOperations.SetBinding(tbObjects, TextBox.TextProperty, myBinding);
tbObjects.Foreground = new SolidColorBrush(Colors.Gray);
}
Note that the source for the binding is TranslationSource.Instance, and the path should be "[Var1]" to indicate its indexer with "Var1" argument.
Side note
Since TranslationSource.Item[string] indexer is read-only, setting the Binding.UpdateSourceTrigger is reduntant. Also, for the same reason, I'd set Binding.Mode to OneWay.

WPF XAML : Load items to combobox in datagrid

I have a WPF datagrid source which has CabinetName as property. I want the selected item to be this Cabinet name and the combobox dropdown to be filled from a new List FCabinetNames. I write this combobox template into my wpf datagrid to implement this functionality.
<DataGridTemplateColumn Header="Cabinet">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding CabinetName}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding FCabinetNames}"></ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
Now the selected item is showing up correctly so TextBlock Text part is fine. But the item source is not loaded fine.
I have this snippet for the item source.
public class FCabinetNames:List<string>
{
BusinessLogic admintasks = new BusinessLogic();
public FCabinetNames()
{
try
{
List<CabinetData> cab1 = admintasks.CabinetDataforGrid();
List<string> fcabinetname = new List<string>();
foreach (var c1 in cab1)
{
this.Add(c1.CabinetName);
}
}
catch
{
}
}
}

Iterate through ComboBox items when using CheckBox as ItemTemplate

I using a ComboBox with CheckBox as ItemTemplate and I want to iterate through all items, get their checked status and write their content to a string if checked is true. The problem is that I am using a SqlDataReader to fill and bind the ComboBox from database and I can't find a way to access the items IsChecked property.
<ComboBox>
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox Click="CheckBox_Click" Content="{Binding}" IsChecked="{Binding Path=IsSelected, Mode=TwoWay}" Tag="{RelativeSource FindAncestor, AncestorType={x:Type ComboBox}}"/>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
I have tried casting the ComboBox items as CheckBoxes on the click event of them this way:
private void CheckBox_Click(object sender, RoutedEventArgs e)
{
for (int i = 0; i < myComboBox.Items.Count; i++)
{
CheckBox cb = (myComboBox.Items[i] as CheckBox);
if (cb.IsChecked == true)
{
myString += "," + myComboBox.SelectedItem.ToString() + "";
}
}
}
but cb always returns NULL. I am guessing it is something with the IsChecked property binding.
I'd like to get this working but I don't want to create an object/class to fill the combobox because I need it to be filled with database. I'd really appreciate any help.
You could do something like this (I'm not stick to MVVM pattern) and this is written on the fly :
public ArrayList List { get; set; }
public MainWindow()
{
InitializeComponent();
SqlDataReader rdr = cmd.ExecuteReader();
List = new ArrayList();
while (rdr.Read()){
List.Add(new Class{ Id = rdr.GetString(0), Value = rdr.GetString(1), IsChecked= rdr.GetString(1) as bool}); //this class will contain the same data schema in your datareader but using properties
}
rdr.Close();
DataContext = List;
}
<ComboBox Name="ComboBox" ItemsSource="{Binding}" >
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox Tag="{Binding Id}" Content="{Binding Name}" IsChecked="{Binding IsChecked}"/>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>

Preselect Value of Treeview inside combobox

I am looking to implement a treeview inside a combobox. Basically I want it to show as a combobox when collapsed but a treeview inside combo box when expanded. When a user clicks on a node, I want it to show in the collapsed combo box. I have got this working so far.
The problem I am having is that how do I show a default value from c# when this combo box is loaded. Please help guys as I am running out of ideas :)
Thanks in advance.
Data Template
<DataTemplate x:Key="TreeViewExpanded" >
<StackPanel>
<TreeView x:Name="DPointTree" Margin="5" ItemsSource="{Binding Datapoint}"
Tag="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ComboBox}}}"
>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Field}">
<TextBlock Text="{Binding Name}"/>
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"/>
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</StackPanel>
<DataTemplate.Triggers>
<DataTrigger Binding = "{Binding Path=SelectedFieldName, Mode=TwoWay}" Value = "">
<Setter Property = "Visibility" Value = "Collapsed"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
Here is the Xaml
<ComboBox Name="cmbFieldName" Width="150" Background="White" ItemsSource="{Binding}" SelectedItem="{Binding SelectedFieldName , Mode=TwoWay}" >
<ComboBox.ItemTemplateSelector>
<local:TreeViewSelector/>
</ComboBox.ItemTemplateSelector>
</ComboBox>
Here is the DataSet passed to this.
Datapoint _datapoint2 = new Datapoint();
_datapoint2.Name = "Alpha";
_datapoint2.FieldID.Add("Contains Elements");
_datapoint2.Field.Add("1 Year");
_datapoint2.Field.Add("2 Year");
_datapoint2.Field.Add("3 Year");
Try this:
private void TreeView_Loaded(object sender, RoutedEventArgs e)
{
TreeView areaTreeView = sender as TreeView;
// Expand the treeview
if (areaTreeView != null)
{
ExpandCollapseTreeNodes(areaTreeView, true);
}
}
public static void ExpandCollapseTreeNodes(ItemsControl parentContainer, bool isExpanded)
{
foreach (Object item in parentContainer.Items)
{
TreeViewItem currentContainer = parentContainer.ItemContainerGenerator.ContainerFromItem(item) as TreeViewItem;
if (currentContainer != null) // && currentContainer.Items.Count > 0
{
//expand the item
currentContainer.IsExpanded = isExpanded;
//if the item's children are not generated, they must be expanded
if (isExpanded && currentContainer.ItemContainerGenerator.Status != GeneratorStatus.ContainersGenerated)
{
//store the event handler in a variable so we can remove it (in the handler itself)
EventHandler eh = null;
eh = new EventHandler(delegate
{
//once the children have been generated, expand those children's children then remove the event handler
if (currentContainer.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated)
{
ExpandCollapseTreeNodes(currentContainer, isExpanded);
currentContainer.ItemContainerGenerator.StatusChanged -= eh;
}
});
currentContainer.ItemContainerGenerator.StatusChanged += eh;
}
//otherwise the children have already been generated, so we can now expand those children
else
{
ExpandCollapseTreeNodes(currentContainer, isExpanded);
}
}
}
}
it is not pretty but works to select a node in the tree
// in code behind after the tree is declared, e.g. after InitializeComponent();
SynchronizationContext.Current.Post(delegate
{
// expand the tree to the selected node after loading
treeView.ExpandAll(); // or if path is known treeView.ExpandPath(...);
SynchronizationContext.Current.Post(delegate
{
treeView.GetContainerFromItem(root.Children[0]).IsSelected = true;
}, null);
}, null);

ComboBox SelectedItem binding not updating

I'm a bit puzzled:
this works:
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Label Content="Rol" />
<ComboBox ItemTemplate="{StaticResource listRollen}"
Height="23" Width="150"
SelectedItem="{Binding Path=SelectedRol, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
ItemsSource="{Binding Path=allRollen, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>
and the property for SelectedRol is:
public TblRollen SelectedRol
{
get { return _selectedRol; }
set
{
if (_selectedRol != value)
{
_selectedRol = value;
OnPropertyChanged("SelectedRol");
}
}
}
But this doesn't work:
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Label Content="Soort" />
<ComboBox ItemTemplate="{StaticResource listSoorten}"
Height="23" Width="150"
ItemsSource="{Binding Path=allSoorten}"
SelectedItem="{Binding Path=SelectedProduct, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</StackPanel>
with following property SelectedProduct:
public TblProduktSoorten SelectedProduct
{
get { return _selectedPSoort; }
set
{
if (_selectedPSoort != value)
{
_selectedPSoort = value;
OnPropertyChanged("SelectedProduct");
}
}
}
somewhere in my code I set SelectedProduct = p.TblProduktSoorten and while debugging, I see the property gets set correctly...
Combobox inside a DataGrid?
If the combobox is in a DataGrid you must add this :
Mode=TwoWay, UpdateSourceTrigger=PropertyChanged
See this : https://stackoverflow.com/a/5669426/16940
Try to use not selected item but value path look at the code sample
<ComboBox Name="projectcomboBox" ItemsSource="{Binding Path=Projects}" IsSynchronizedWithCurrentItem="True" DisplayMemberPath="FullName"
SelectedValuePath="Name" SelectedIndex="0" Grid.Row="1" Visibility="Visible" Canvas.Left="10" Canvas.Top="24" Margin="11,6,13,10">
</ComboBox>
the binding property is
public ObservableCollection<Project> Projects
{
get { return projects; }
set
{
projects = value;
RaisePropertyChanged("Projects");
}
}
This might be related to the fact that apparently attribute order does matter, in your second case the ItemsSource and SelectedItem declarations are swapped.
If you set the SelectedProduct property when SelectedProduct is changed in the property changed event handler, you need to set this property asynchronously.
private void ViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "SelectedProduct")
App.Current.Dispatcher.InvokeAsync(() => SelectedProduct = somevalue);
}
My problem was caused by my own tired brain. Same symptom, maybe it will kick you into seeing your problem.
Setting the SelectedItem must be given an item in the List!! (duhh) Normally this happens naturally but I had a case I got a "Role" from another service (Same object type) and was trying to set it and expecting the combobox to change! ;(
instead of -
Roles = roles;
CurrentRole = role;
remember to do this -
Roles = roles;
CurrentRole = roles.FirstOrDefault(e=> e.ID == role.ID); //(System.Linq)
I don't know if you fixed it yet, but I encountered the same issue today.
It was fixed by making sure the collection for selecteditems was an ObservableCollection.
I think this problem is caused by the type of ItemSource and SelectedItem is mitchmatched.
For example, if the ItemSource is binded to a List of int and the SelectedItem is binded to a string. If you set selected item to null or empty string, the combobox cannot know what item is selected. So the combobox will show nothing.
This might be old but I have not seen the trick that did it for me; I had to add NotifyOnSourceupdate=true to my SelectedItem in the ComboBox
This had me stumped for a while inside a DataGrid, using SelectedItem. Everything was fine but I am deserializing the app state which loads the items and also has a selected item. The collection was there but the selected isn't actually visible until I used the Text="{Binding Path=Score.SelectedResult.Offset}"
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox ToolTip="Score offset results"
ItemsSource="{Binding Score.SearchResults,UpdateSourceTrigger=PropertyChanged}"
SelectedItem="{Binding Score.SelectedResult, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Text="{Binding Path=Score.SelectedResult.Offset}"
SelectedValuePath="Offset"
DisplayMemberPath="Offset"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>

Categories