Finding particular check box from the checkbox list in wpf - c#

My code is as below
<ListBox x:Name="lstbxRefMarket" Margin="5,5,5,5" BorderThickness="0" Height="100" VerticalAlignment="Stretch">
<ListBox.ItemTemplate>
<HierarchicalDataTemplate>
<CheckBox Name="chkbxRefMarket" Content="{Binding Market}" CommandParameter="{Binding MarketId}" Tag="{Binding MarketId}" IsChecked="{Binding Checked}" Checked="chkbxRefMarket_Checked" Unchecked="chkbxRefMarket_Unchecked" Foreground="Blue"/>
</HierarchicalDataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Now in code behind I need to uncheck the particular checkbox with MarketId as 8 from chkbxRefMarket list
As you see from the code checkbox will be having CommandParameter ,Tag as MarketId
How can I find the particular checkbox with that market id in the list .

Why not simply find the right item and set its Checked property. The associated CheckBox is bound to that property and will automatically be unchecked.
The code below assumes that your data item class is MyItem.
IEnumerable<MyItem> items = lstbxRefMarket.Items.OfType<MyItem>();
MyItem item = items.FirstOrDefault(i => i.MarketId == 8);
if (item != null)
{
item.Checked = false;
}

Related

Dynamically add label/checkBox-Combo and put code behind

I have build a dynamically-generated label/checkbox-List.
The label-content gets his content from a list with some application-names. The Checkbox(es) share a single CheckBox_Click-Event, that is triggered when i hit one of the checkboxes. The Problem i got now is, i can't identify which checkbox is clicked. Because i generate the controls i can't put a name through binding behind the controls. I'm not-so-experienced in creating gui's through code. Hope you guys can help me a bit.
// This part builds my label/combo-List through a FileInfo-List
Fields = new System.Collections.ObjectModel.ObservableCollection<Field>();
foreach (var app in GetPrograms())
{
Fields.Add(new Field() {Name = app.Name, Length = 100, Required = true});
}
FieldsListBox.ItemsSource = Fields;
// Here i got the Click-Event.. but i can't identify which Checkbox is clicked
private void CheckBox_Click(object sender, RoutedEventArgs e)
{
CheckBox senderChk = sender as CheckBox;
switch (senderChk.Name)
{
//case "checkBox1": // do something
//case "checkBox2": // do something
}
}
<!-- And finally the xaml-Code, note the Bindings on label and checkbox -->
<Grid>
<ListBox x:Name="FieldsListBox">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Label Content="{Binding Name}" VerticalAlignment="Center"></Label>
<CheckBox IsChecked="{Binding Checked}" Click="CheckBox_Click" Margin="5,0,0,0"></CheckBox>
</StackPanel>
Because i already have a list of filenames, i thought i can bind the names on the checkboxes, so i know which checkbox was clicked and can manage the right programmname.
You did this to bind the checked propierty to the comboBox.
<CheckBox IsChecked="{Binding Checked}" ... ></CheckBox>
Do the same and Bind the propierty Uid (used to identify controls in WPF) of the combobox like this:
<CheckBox ... Uid="{Binding Name}" ... ></CheckBox>
and use it in your switch.

how to set checkbox in listbox for specific item in listbox C# WPF

I have such a listbox like below:
<ListBox x:Name="listBox" HorizontalAlignment="Left" Height="385" Margin="21,138,0,0" VerticalAlignment="Top" Width="273" ItemsSource="{Binding Path=locationList}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Button Name="btnDelete" Click="btnDelete_Click" Width="15" Height="15" HorizontalAlignment="Center" VerticalAlignment="Center" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" Content="x" />
<CheckBox Name="checkBox" />
<TextBlock Name="textBox" Text="{Binding}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
And what I would like to do is to set checkbox for specific item this listbox.
I am trying to do it:
private void button4_Click(object sender, RoutedEventArgs e)
{
for(int i = 0; i < listBox.Items.Count; i++)
{
listBox.Items[i].checkBox = false;
}
}
I know I am doing an error. I would like to cast it to object of item and then set an item's property (this checkbox) to false. May anyone correct me ? Thank you in advance.
edit:
Before I was trying to do it this way:
foreach (var item in listBox.SelectedItems)
{
item.
}
but all possibilities I have got are just standard methods: Equals, GetHashCode, GetType, ToString... How I may refer to checkbox ?
Moreover I will supply my question with the insight. I would like to find a specific item by text which is in line in listbox (item) and then change checkbox for this item (same row in listbox).
Second logic to be implemented is to set all rows to selected or unselected (this is what I am trying to do now).
Thank you for response.
for (int i = 0; i < listBox.Items.Count; i++)
{
var item = listBox.ItemContainerGenerator.ContainerFromItem(listBox.Items[i]) as ListBoxItem;
var template = item.ContentTemplate as DataTemplate;
ContentPresenter myContentPresenter = FindVisualChild<ContentPresenter>(item);
CheckBox myCheckBox = (CheckBox)template.FindName("checkBox", myContentPresenter);
myCheckBox.IsChecked = true;
}
Likewise you can find the TextBlock with (note, you named it "textBox" not "textBlock")
TextBlock myTextBlock = (TextBlock)template.FindName("textBox", myContentPresenter);
FindVisualChild can be found here FindVisualChild reference issue

ListBox.ItemContainerGenerator.ContainerFromIndex Returns null

For my Windows Phone 8 App I have a Listbox element like below;
when I press multiselect icon on AppBar, I want to show checkboxes inside DataTemplate.
So users can make multiselect on items.
I have 50 elements bound on this Listbox and always at the index 11 ItemContainerGenerator.ContainerFromIndex returns null, plus some other items at rest of the list. So around 10 items out of 50 as returning as null.
There are some answers for WPF like applying Dispatcher.BeginInvoke or UpdateLayout, ScrollIntoView but none of them is working.
On the other hand if I scroll through list and then press AppBar icon it just works fine. But users can directly press on icon right after data bound and they will not see some of the checkboxes.
Is there any workaround for this issue for Windows Phone 8?
<ListBox Name="ResultListBox" ItemsSource="{Binding}"
SelectionChanged="ResultListBox_OnSelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,10" Orientation="Horizontal">
<StackPanel Orientation="Horizontal">
<CheckBox Name="CheckBox" Visibility="Collapsed">
</CheckBox>
<Image Source="{Binding url}"
Width="125"
Height="125"
VerticalAlignment="Top"
Margin="0,0,5,0"></Image>
</StackPanel>
<StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding title}"
VerticalAlignment="Top"
FontFamily="Portable User Interface"></TextBlock>
</StackPanel>
<StackPanel>
<TextBlock Text="{Binding description}"
FontFamily="Portable User Interface"></TextBlock>
</StackPanel>
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
void appBarButtonSelect_Click(object sender, EventArgs e)
{
//Dispatcher.BeginInvoke(delegate
//{
//});
for (int i = 0; i < ResultListBox.Items.Count; i++)
{
//ResultListBox.UpdateLayout();
//ResultListBox.ScrollIntoView(i);
DependencyObject item = ResultListBox.ItemContainerGenerator.ContainerFromIndex(i);
if (item != null)
{
CheckBox checkBox = FindFirstElementInVisualTree<CheckBox>(item);
if (checkBox != null)
{
checkBox.Visibility = Visibility.Visible;
}
}
else
{
Debugger.Break();
}
}
}
I think you're using ScrollIntoView + UpdateLayout incorrectly,
You're passing it an index, when it needs an object that is directly related to the ItemsSource
So if your ItemsSource is an ObservableCollection do this:
object o = ((ObservableCollection<sample_model>)this.myListBox.ItemsSource)[INDEX];
this.myListBox.ScrollIntoView(o); // call this first
this.myListBox.UpdateLayout(); // call this second
Then your ItemContainerGenerator.ContainerFromIndex(INDEX) will not be NULL.

WPF Get CheckBoxes inside ListBox in code

I have this List box and I want to search for its items which were selected (IsChecked=true) by user
<CheckBox Style="{StaticResource ResourceKey=CheckBoxes}"
Name="chkBoxSelectAllStaff" Content="Select All">
</CheckBox>
<ListBox Name="lstStaffs" MaxHeight="250" MinHeight="50" Margin="0,5,5,5" Width="350"
ScrollViewer.VerticalScrollBarVisibility="Auto" HorizontalAlignment="Right"
HorizontalContentAlignment="Right">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Style="{StaticResource ResourceKey=CheckBoxes}" IsChecked="{Binding ElementName=chkBoxSelectAllStaff, Mode=OneWay, Path=IsChecked}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding FirstName}" Margin="0,0,3,0"></TextBlock>
<TextBlock Text="{Binding LastName}" Margin="0,0,3,0"></TextBlock>
<TextBlock Text="{Binding CellphoneNumber}" Margin="0,0,3,0"></TextBlock>
</StackPanel>
</CheckBox>
</DataTemplate>
</ListBox.ItemTemplate>
I want to do something like this
foreach(var item in lstStaff.Items){
if((CheckBox) item).IsChecked){
//do something
}
}
And also I am binding the data this way :
//staff is my entity object containing Id, FirstName, LastName, CellphoneNumber
lstStaffs.ItemsSource = args.Result; // comes from webservice call and is Staff[]
lstStaffs.UpdateLayout();
But I get Staff object in lstStaffs.Items!!, So how can I iterate over selected(IsChecked=true) items(staffs) ...
Tnx
From the How to: Find DataTemplate-Generated Elements page at MSDN:
// Getting the currently selected ListBoxItem
// Note that the ListBox must have
// IsSynchronizedWithCurrentItem set to True for this to work
ListBoxItem myListBoxItem = (ListBoxItem)(myListBox.ItemContainerGenerator.
ContainerFromItem(myListBox.Items.CurrentItem));
// Getting the ContentPresenter of myListBoxItem
ContentPresenter myContentPresenter = FindVisualChild<ContentPresenter>(myListBoxItem);
// Finding textBlock from the DataTemplate that is set on that ContentPresenter
DataTemplate myDataTemplate = myContentPresenter.ContentTemplate;
TextBlock myTextBlock = (TextBlock)myDataTemplate.FindName("textBlock",
myContentPresenter);
// Do something to the DataTemplate-generated TextBlock
MessageBox.Show("The text of the TextBlock of the selected list item: "
+ myTextBlock.Text);
This shows you how to get access to elements defined in a DataTemplate. However, if you just want to get access to the items from the collection that have been selected, there is a much simpler way:
var selectedItems = lstStaffs.SelectedItems;
You must set the SelectionMode to Multiple or Extended for this to work.

Keep same selected Item in a ListView when the collection it is bound to is refreshed

I have a ListView that is bound to an ObservableCollection which is itself derived from an IQueryable. When I refresh the collection, after items are added, edited or a button is clicked (to see if the database has new items from other users). The listbox refreshes and selects the first item in the collection.
I want to keep the same selected item (If it still exists) after a refresh but because the Collection has been replaced I cannot seem to compare equality between an item in the old collection and the new one. All attemtps never have a match.
How should this be done?
Below are some relevant code snipets if anyone wants to see them:
The ListView, MouseDoubleClick Event opens an edit window
<ListView x:Name="IssueListView"
ItemsSource="{Binding Issues}"
ItemTemplate="{StaticResource ShowIssueDetail}"
IsSynchronizedWithCurrentItem="True"
MouseDoubleClick="IssueListView_MouseDoubleClick" />
It's DataTemplate
<DataTemplate x:Key="ShowIssueDetail">
<Border CornerRadius="3" Margin="2" MinWidth="400" BorderThickness="2"
BorderBrush="{Binding Path=IssUrgency,
Converter={StaticResource IntToRYGBBorderBrushConverter}}">
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Path=IssSubject}"
Margin="3" FontWeight="Bold" FontSize="14"/>
<!--DataTrigger will collapse following panel for simple view-->
<StackPanel Name="IssueDetailPanel" Visibility="Visible" Margin="3">
<StackPanel Width="Auto" Orientation="Horizontal">
<TextBlock Text="Due: " FontWeight="Bold"/>
<TextBlock Text="{Binding Path=IssDueDate, StringFormat='d'}"
FontStyle="Italic" HorizontalAlignment="Left"/>
</StackPanel>
<StackPanel Width="Auto" Orientation="Horizontal">
<TextBlock Text="Category: " FontWeight="Bold"/>
<TextBlock Text="{Binding Path=IssCategory}"/>
</StackPanel>
</StackPanel>
</StackPanel>
</Border>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Path=StatusBoardViewModel.ShowDetailListItems,
RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type Window}}}" Value="False">
<Setter TargetName="IssueDetailPanel"
Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
The Issues collection is refreshed by executing a QueryIssues Method that builds a Linq To SQL query programatically based on bound controls. IssuesQuery is an IQueryable property
public void QueryIssues()
{
// Will show all items
IssuesQuery = from i in db.Issues
orderby i.IssDueDate, i.IssUrgency
select i;
// Filters out closed issues if they are not to be shown
if (includeClosedIssues == false)
{
IssuesQuery = from i in IssuesQuery
where i.IssIsClosed == false
select i;
}
// Filters out Regular Tasks if they are not to be shown
if (showTasks == false)
{
IssuesQuery = from i in IssuesQuery
where i.IssIsOnStatusBoard == true
select i;
}
// Filters out private items if they are not to be shown
if (showPrivateIssues == false)
{
IssuesQuery = from i in IssuesQuery
where i.IssIsPrivate == false
select i;
}
// Filters out Deaprtments if one is selected
if (departmentToShow != "All")
{
IssuesQuery = from i in IssuesQuery
where i.IssDepartment == departmentToShow
select i;
}
Issues = new ObservableCollection<Issue>(IssuesQuery);
}
Because you are getting completely new objects there is no other way to match equality than to find the item that matches the old (if it exists) and select it. You are replacing your collection which means that you have to track the selected item yourself.
Other options:
You could keep a collection and manually add/remove items based on the query results (ie don't destroy the current item).
One way to do this in your view model:
// The ListView's SelectedItem is bound to CurrentlySelectedItem
var selectedItem = this.CurrentlySelectedItem;
// ListView is bound to the Collection property
// setting Collection automatically raises an INotifyPropertyChanged notification
this.Collection = GetIssues(); // load collection with new data
this.CurrentlySelectedItem = this.Collection.SingleOrDefault<Issue>(x => x.Id == selectedItem.Id);
When faced with this issue in the past i have wrapped the items i want to display in a small view model class, then given each an extra property IsSelected and then bound this property to the ListBoxItem using an ItemContainerStyle. That way i keep track of what is selected.

Categories

Resources