GetItemAt returning null value instead of ComboBoxItem - c#

I have two ComboBox with same items.
I am trying to get the ComboBoxItem of a ComboBox by Index but NULL value is being returned.
My code is:
var index = comboBox1.SelectedIndex;
ComboBoxItem item = comboBox2.Items.GetItemAt(index) as ComboBoxItem; // item is null here
//item = (ComboBoxItem)comboBox2.ItemContainerGenerator.ContainerFromItem(comboBox1.SelectedItem);
//also tried above line but same result(null)
And XAML:
<ComboBox Name="comboBox1" ItemsSource="{Binding ExistingModuleGroups}" SelectedItem="{Binding SelectedModuleGroup}" SelectionChanged="ComboBox1_SelectionChanged">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<ComboBox Name="comboBox2" ItemsSource="{Binding ExistingModuleGroups}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
private void comboBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (e.AddedItems.Count > 0)
{
if (comboBox2.Items.Count > 0)
{
var index = comboBox1.SelectedIndex;
ComboBoxItem item = comboBox2.Items.GetItemAt(index) as ComboBoxItem; // item is null here
//item.IsEnabled = false;
}
}
}
Any idea...

The ItemsControl.Items property stores the actual data, not the generated ComboBoxItems (unless you've manually added objects of type ComboBoxItem to the Items collection).
You were close with that second piece of code you've commented, but you were looking for an item from the first combo in the second combo. Since you are probably not using the same instances for both combos, that won't work.
The correct thing would probably be this. Similar to what you've already tried, but with some key differences:
var index = comboBox1.SelectedIndex; // Get the index from the first combo
var item = (ComboBoxItem)comboBox2.ItemContainerGenerator
.ContainerFromIndex(index); // And get the ComboBoxItem from that index
// in the second combo

Related

Datagrid ComboBox binding two values

I have a combobox which is populated from a list of names which were obtained from selecting from an Observable collection. However, associated with those names is an ID also in that Observable collection. The goal is when the user selects a new name (Say changes "John" to "Jill") I will be able to obtain the ID, not just the name. The only way I can think of doing this is storing the ID also in the combobox somehow. But I don't know how to do that with binding.
<DataGridTemplateColumn Header="Name ">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox x:Name="namescombo" ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=DataContext.Names}"
SelectedItem="{Binding Name, UpdateSourceTrigger=PropertyChanged}" FontSize="12" Background="White" FontFamily="Cambria" BorderBrush="White" BorderThickness="0"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
C#
ObservableCollection<Name> Names = new ObservableCollection<Name>();
Name twofields = new Name();
var NamesQuery =
from p in dataEntities.Names
select new { p.Name, p.Id };
foreach (var p in NamesQuery)
{
Names.Add(new Name
{
ID = p.Id,
Name = p.Name
});
}
Names = Names.Select(p => p.Name).Distinct().ToList();
A ComboBox contains properties for both the DisplayMemberPath and the SelectedValuePath, so you could use it to tell the ComboBox to identify items by the "Id" property, but display the "Name" property to the user.
For example,
<DataGridTemplateColumn Header="Name ">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox
ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=DataContext.Names}"
DisplayMemberPath="Name"
SelectedValuePath="Id"
SelectedValue="{Binding SelectedId}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
I would recommend using SelectedValue over SelectedItem because WPF compares SelectedItem by .Equals() which defaults to comparing items by reference, and if your SelectedItem is not the exact same reference as the item in your ItemsSource, it won't get selected.
For example, SelectedItem = new Person(1, "Test"); would probably not set the selected item correctly, while SelectedItem = ItemsSource[0] would since it refers to an item that exists in the ItemsSource.
Also, it frequently makes more sense to store just the Id of the selected item on a row instead of the entire object :)
You can bind directly to Name object collection and set DisplayMemberPath to Name property so that strings are shown on GUI but in essence you have complete object binded to comboBox.
This way you can bind SelectedItem to Name object and can access Id and Name property.
<ComboBox ItemsSource="{Binding Names}" // Collection of name objects.
DisplayMemberPath="Name"
SelectedItem="{Binding SelectedNameObject}"/> // Object of type Name.

how to retrieve All Checked Items from radTreeListView SelectedItems Collection

how do i retrieve all Checked Items from a radTreeListView SelectedItems Collection in c#?
The example below from Retrieve All Checked Items isn't working at all.
foreach ( object checkedItem in radTreeView.CheckedItems )
{
// Get the container(RadTreeViewItem) of the checked item
RadTreeViewItem container = radTreeView.ContainerFromItemRecursive( checkedItem );
// Add your logic for handling the checked item scenario here
}
The XML for the RadTreeListView is
<telerik:RadTreeListView x:Name="radTreeListView" ItemsSource="{Binding Items}"
AutoGenerateColumns="False" Grid.RowSpan="2" SelectionChanged="radTreeListView_SelectionChanged" SelectionMode="Extended" SelectedItem="{Binding SelectedItem, Mode=TwoWay}" SelectionChanging="radTreeListView_SelectionChanging" BeginningEdit="radTreeListView_BeginningEdit">
<telerik:RadTreeListView.ChildTableDefinitions>
<telerik:TreeListViewTableDefinition ItemsSource="{Binding Items}" />
</telerik:RadTreeListView.ChildTableDefinitions>
<telerik:RadTreeListView.Columns>
<telerik:GridViewSelectColumn/>
<telerik:GridViewDataColumn DataMemberBinding="{Binding Name}" Header="Name" />
</telerik:RadTreeListView.Columns>
</telerik:RadTreeListView>
SelectedItems is the key!
I prepared SampleData as described here and capture checked items with following code.
System.Collections.ObjectModel.ObservableCollection<object> selected_items = radTreeListView.SelectedItems;
foreach (object item in selected_items)
{
WarehouseItem warehouseitem = (WarehouseItem)item;
MessageBox.Show(warehouseitem.Name);
}

Getting Text from ComboBox in WPF

I have a ComboBox in WPF and I cant access its selected item text.
I have tried
cbItem.Text;
cbItem.SelectedItem.ToString();
XAML:
<ComboBox Name="cbItem" SelectedValuePath="ITEM_ID">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding ITEM_NAME}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
Do ITEM_ID and ITEM_NAME come from an object?
String textComboBox = ((ITEMCLASS)cbItem.SelectedItem).ITEM_NAME.ToString();
Try
cbItem.SelectedValue.ToString()
This will work only if combobox values are same as the combobox text
EDIT:
Solution 1
You have to get access to the ComboBox's TextBox:
var str = (TextBox)cbItem.Template.FindName("PART_EditableTextBox", cbItem);
Then you can access the SelectedText property of that TextBox:
var selectedText = str.SelectedText; // This will give you text of selected item
Solution 2
ComboBoxItem typeItem = (ComboBoxItem)cbItem.SelectedItem;
string value = typeItem.Content.ToString();// This will give you text of selected item
Try this
<ComboBox Name="cbItem" SelectedValuePath="ITEM_ID">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Name="txtblck" Text="{Binding ITEM_NAME}" />
</DataTemplate>
</ComboBox.ItemTemplate>
TextBox str = (TextBox)cbItem.FindName("txtblck");
string text = str.Text;

how to Remove item from one Listbox and add into another Listbox?

I am trying to remove selected item from one listbox and add that into new listbox as follows code
Binding on PageLoad:
Getting the records from database into a DataTable and bind that to Listbox.
lstBox1.DataContext = dtData;
Code Bind:
List<object> _selecteditems = new List<object>();
foreach (var item in lstBox1.SelectedItems)
{
_selecteditems.Add(item);
}
foreach (var item in _selecteditems)
{
lstBox1.Items.Remove(item);
lstBox2.Items.Add(item);
}
Design:
<ListBox Name="lstBox1" ItemsSource="{Binding}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding ID}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<ListBox Name="lstBox2" ItemsSource="{Binding}" >
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding ID}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I am getting an error when removeing the item "Operation is not valid while ItemsSource is in use. Access and modify elements with ItemsControl.ItemsSource instead."
Don't manipulate the items via the Items property, instead add/remove items from the List that the ListBox is bound to:
<ListBox Name="lstBox1" ItemsSource="{Binding myListProperty}">
...etc...
</ListBox>
If your myListProperty returns a collection that implements INotifyCollectionChanged (like the ObservableCollection does) then the listboxes will automatically show the new items as they are added and the removed items will instantly disappear.
I tried by following way and its working for me.
List<object> _selecteditems = new List<object>();
foreach (var item in lstBox1.SelectedItems)
{
_selecteditems.Add(item);
}
foreach (var item in _selecteditems)
{
DataRow dr = dtSelctedDest.NewRow();
dr[0] = ((DataRowView)item).Row[0].ToString();
dr[1] = ((DataRowView)item).Row[1].ToString();
dtSelctedItem.Rows.Add(dr);
dtAllItem.Rows.Remove(dtAllItem.Rows.Remove.Select(string.Format("ID='{0}'", ((DataRowView)item).Row[0].ToString()))[0]);
}
lstBox1.DataContext = dtAllItem;
lstBox2.DataContext = dtSelctedItem;

i have a listbox and check box and how can i find the how much check box checked in wpf

I want to find how much check box is checked by code :
<Grid Width="440" >
<ListBox Name="listBoxZone" ItemsSource="{Binding TheList}" Background="White" Margin="0,120,2,131">
<ListBox.ItemTemplate>
<HierarchicalDataTemplate>
<CheckBox Name="CheckBoxZone" Content="{Binding StatusName}" Tag="{Binding StatusId}" Margin="0,5,0,0" VerticalAlignment ="Top" />
</HierarchicalDataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
Here is my code where i want to find how much check box is checked ?
for (int i = 0; i < listBoxZone.Items.Count; i++)
{
if (CheckBoxZone.IsChecked == true )
{
}
}
You could add an IsChecked property of type Nullable<bool> (could be written as bool?) to your data item class and two-way bind the CheckBox.IsChecked property:
<CheckBox Name="CheckBoxZone" IsChecked={Binding IsChecked, Mode=TwoWay} ... />
Now you can simple iterate over all items and check their IsChecked state:
int numChecked = 0;
foreach (MyItem item in listBoxZone.Items)
{
if ((bool)item.IsChecked) // cast Nullable<bool> to bool
{
numChecked++;
}
}
or with Linq:
int numChecked =
itemsControl.Items.Cast<MyItem>().Count(i => (bool)i.IsChecked);
And just a note: why do you use HierarchicalDataTemplate in a ListBox, where DataTemplate would be sufficient?
Use OfType Method of LINQ
int result =
listBoxZone.Items.OfType<CheckBox>().Count(i => i.IsChecked == true);
I used OfType instead of Cast because OfType will work even if there a single checkbox item or all items are checkboxes.
In case of Cast it will give error if even a single item is not checkbox.

Categories

Resources