How to select all checkbox inside telerik combox on checbox Checked event? - wpf

I have on checkbox inside telerik combo control. If User click on "All" option from checkbox list then I want select all checkboxs.
checkbox values.
My Sample code is below.
<telerik:RadComboBox Name="rcbDays" Grid.Row="1" Grid.Column="1" Width="200" HorizontalAlignment="Left" ItemsSource="{Binding MonthDaysList}" VerticalAlignment="Center" >
<telerik:RadComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox Name="chkDays" Content="{Binding DaysText}"
Tag="{Binding DaysValue}" Checked="chkDays_Checked" />
</StackPanel>
</DataTemplate>
</telerik:RadComboBox.ItemTemplate>
</telerik:RadComboBox>
private void chkWeeks_Checked(object sender, RoutedEventArgs e)
{
//Here I want code for selecting all checkboxes.
}

The items that you bound the ComboBox to should have a property like IsSelected, then you should bind IsChecked of the data-template CheckBox to that. Then you just need to iterate over the source collection and set IsSelected=true on all items.
e.g.
public class MyClass : MyBaseClass // Whatever you may have called it,
{
public bool IsSelected { ... }
public string DaysText { ... }
//...
}
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked="{Binding IsSelected}" Content="{Binding DaysText}" Tag="{Binding DaysValue}" />
</StackPanel>
</DataTemplate>
//In the handler that is supposed to select all
foreach (var item in MonthDaysList) item.IsSelected = true;
Of course the property needs to have change notifications.
(Also a note on usability: I do not thing that ComboBoxes should contain CheckBoxes, if you need multiple item selection use a ListBox)

You need to take one more property isSelected as said by H.B.
add IsChecked="{Binding IsSelected}" to CheckBox tag in xaml file. Create one property in the appropriate class i.e. public bool isSeleted.......
When you get in to event chkWeeks_Checked() in this function get reference of the ComboBox item source like objList = (TypeCastYourClassType)YourComboBox.ItemSource;... Now the objList contains all checkbox items. Iterate through objList collection and get isSeleted property for each and every single item and that's done....
In your case
MonthDayList = (TypeCastYourClassType)rcbDays.ItemSource;
for(int i=0;i<MonthDayList.Count;i++)
{
MonthDayList[i].isSelected = true;
}

Here is some good discussion for allowing multiple values to be selected in the telerik combobox.
It uses checkbox within combobox
http://codedotnets.blogspot.in/2012/02/checkboxes-in-comboxes-to-allow.html
Thanks :)

Related

WPF: How to hide specific tab item in TabControl that with DataTemplate bind to views

I have a WPF xaml TabControl defined as below, how to set Visibility to Collapsed for the tab item based on binding?
Current code:
<TabControl>
<DataTemplate DataType="{x:Type foo:FooViewModel}">
<foo:FooView/>
</DataTemplate>
<DataTemplate DataType="{x:Type bar:BarViewModel}">
<bar:BarView/>
</DataTemplate>
<TabControl/>
What I want to implement to only hide foo TabItem based on condition, but seems it cannot specify the target name?? E.g. hide the template which name is Foo. Thanks for your help, have a nice day.
<TabControl ItemsSource="{Binding ParentModel}">
<DataTemplate x:Name="Foo" DataType="{x:Type foo:FooViewModel}">
<foo:FooView/>
</DataTemplate>
<DataTemplate x:Name="Bar" DataType="{x:Type bar:BarViewModel}">
<bar:BarView/>
</DataTemplate>
<TabControl.ItemContinerStyle>
<Style TargetType="TabItem" 'e.g. TargetName="Foo"<==========='>
<Style.Triggers>
...Some trigger condition ignored here
<Setter Property="Visibility" Value="Collapsed" />
</Style.Triggers>
</Style>
<TabControl.ItemContinerStyle/>
<TabControl/>
Hiding the TabItem element is visually equivalent to removing the element.
Since you use data templating, the usual procedure would be to filter the source collection based on your condition to remove the data model. Removing the data model will result in the corresponding container (defined by the DataTemplate) not being rendered i.e. it will be hidden.
In WPF you always focus on the data models and not on their containers. It makes thinks a lot easier.
In the view model that defines the ParentModel property, you can define the filter by accessing the ICollectionView of the source collection:
private void ApplyFilter()
{
ICollectionView parentModelView = CollectionViewSource.GetDefaultView(this.ParentModel);
// Remove all items from the view that satisfy the condition
parentModelView.Filter = Predicate;
}
private bool Predicate(object collectionItem)
{
// TODO::Implement condition: return 'true' to hide the item from the view
}
If you want to filter the view directly (not recommended) you can access the ItemsControl.Items property to obtain the current ICollectionView:
private void OnMainWIndowLoaded(object sender, EventArgs e)
{
this.TabControl.Items.Filter = Predicate;
}
private bool Predicate(object collectionItem)
{
// TODO::Implement condition: return 'true' to hide the item from the view
}
Can't you simply control it on the element?
<TabControl>
<TabItem Header="Tabitem 1" Visibility="{Binding TabItem1Visibility, Converter={StaticResource BoolToVisibilityConverter}}"/>
<TabItem Header="Tabitem 2" />
<TabItem Header="Tabitem 3" />
</TabControl>
where TabItem1Visibility is a property in your VM:
private bool _tabItem1Visibility;
public bool TabItem1Visibility
{
get { return _tabItem1Visibility; }
set
{
_tabItem1Visibility = value;
OnPropertyChanged();
}
}
Notes:
BoolToVisibilityConverter's Convert method must return Collapse in case the value is false, not Hidden.
If you set TabItem1Visibility to false while the tab is selected, the content will still shown up, so you have to add SelectedItem="{Binding SelectedTab, Mode=TwoWay}" to TabControl and update it properly.

Hiding Items of a ListBox which has Datatemplate in Codebehind WPF

I Have a listbox with DataTemplate assigned to its' ItemTemplate as below:
<ListBox Name="DayOverview">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Width="125" Background="Transparent" Orientation="Horizontal" MouseLeftButtonDown="DayOverview_MouseLeftButtonDown">
<Label Content="{Binding Owner}"/>
<Label Content="{Binding Subject}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I want to set some of its' Items Visiblity to collapse in codebehind like below:
(DayOverview.Items[i] as ListBoxItem).Visibility = Visibility.Collapsed;
but I can't convert Its' Items to ListBoxItem or any other control, Items are type of a class. Is it possible to hide Items of a ListBox with datatemplate in C#?
The DayOverview.Items collection will contain the items you bound the ItemsSource property to. It is the data not the Visual container. A ListBox will generate a ListBoxItem Container for each of your Items using ItemContainerGenerator.
You can get the visual Container from data item using ItemContainerGenerator's ContainerFromIndex method.
Try this:
DayOverview.ItemContainerGenerator.ContainerFromIndex(i) as ListBoxItem).Visibility = Visibility.Collapsed;
That’s looks like a job for the CollectionViewSource.
var cvs = CollectionViewSource.GetDefaultView(listbox.Items);
cvs.Filter = item => ((ItemType) item).Name == "Bob"; // assign a Filtermethode like this
cvs.Filter = FilterMethod; // or like this
private bool FilterMethod(object obj)
{
var item = (ItemType) obj;
return item.Name == "Bob";
}
the CollectionViewSource uses a Predicate with determines if an item should be shown or not.

Binding TextBlock based on selection in ComboBox

When I make selection in ComboBox, and then type some text in TextBox, I want to have visible AutoSuggestion list of ID or FirstName or LastName (based on ComboBox Selection) that contains typed string in TextBox. Like this, now it works only for FirstName.
I have problem to somehow set dynamically binding for TextBlock.
Please Help.
Thanks in advance! Marina
I have ComboBox:
<ComboBox Height="23" Name="cbAttrib" Width="120" Margin="0,8,0,0">
<ComboBoxItem>ID</ComboBoxItem>
<ComboBoxItem>FirstName</ComboBoxItem>
<ComboBoxItem>LastName</ComboBoxItem>
</ComboBox>
I have TextBox:
<TextBox Name="txtSearch" TextChanged="txtAutoSuggestName_TextChanged"/>
And this ListBox:
<ListBox Name="listBoxSuggestion" Visibility="Hidden" SelectionChanged="ListBox_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock DataContext="{Binding FirstName}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
and in code I have this methods:
private void txtAutoSuggestName_TextChanged(object sender, TextChangedEventArgs e)
{
listBoxSuggestion.Items.Clear();
if (txtSearch.Text != "")
{
ComboBoxItem cb = (ComboBoxItem)cbAttrib.SelectedItem;
Collection<Person> namelist = proxy.PersonSearch(txtSearch.Text, cb.Content.ToString());
if (namelist.Count > 0)
{
listBoxSuggestion.Visibility = Visibility.Visible;
foreach (var obj in namelist)
{
listBoxSuggestion.Items.Add(obj);
}
}
}
else
{
listBoxSuggestion.Visibility = Visibility.Hidden;
}
}
private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (e.AddedItems.Count > 0)
{
txtSearch.Text = (e.AddedItems[0] as Person).FirstName.ToString();
listBoxSuggestion.Visibility = System.Windows.Visibility.Hidden;
}
}
You are not binding the Text so nothing will display
You just bind the DataContext, which does nothing if there are no additional bindings which will be relative to it. Just swap that (or add Text="{Binding}" which will bind to the DataContext which is the FirstName) and if your logic is correct it should work.
(Instead of clearing and adding to Items you should just set the ItemsSource instead. listBoxSuggestion.ItemsSource = namelist;)
Edit: To make the binding work for different suggestions change the binding path to Value and make the ItemsSource a collection of some simple objects with a Value property (e.g. use LINQ and anonymous objects).

How to Identify button for list item

How do i access the object UserNames, that is bound to the list??
What i did so far:
Item of the list is object in my case:
new List<UserNames>();
this.users.Add(new UserNames() {Id = 1, UserName = "name 1"});
I am using data template for which i have label and button.
My List is as follows:
<ListBox Grid.Column="1" Grid.Row="1" Name="listBox1" ItemsSource="{Binding}" SelectedValuePath="Id">
<ListBox.ItemTemplate>
<DataTemplate>
<WrapPanel Orientation="Vertical">
<StackPanel>
<Label Content="{Binding UserName}" />
</StackPanel>
<StackPanel Name="ButtonStackPanel">
<Button Name="MyButton" Content="Click Me" Click="MyButton_Click">
</Button>
</StackPanel>
</WrapPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Where my method for Button is. As you can see i did try to utilise the parent option, but without sucess
private void MyButton_Click(object sender, RoutedEventArgs e)
{
//StackPanel panel = (StackPanel)((Button)sender).Parent;
//WrapPanel wrapPanel = (WrapPanel) panel.Parent;
//ListItem listItem = (ListItem) wrapPanel.Parent;
//ListBox box = (ListBox) listItem.Parent;
//UserNames itemToReport = (UserNames) (box.SelectedItem);
//MessageBox.Show(itemToReport.UserName);
}
You can use the Button's DataContext, since it will be your UserName object
private void MyButton_Click(object sender, RoutedEventArgs e)
{
Button b = sender as Button;
UserNames data = b.DataContext as UserNames;
MessageBox.Show(data.UserName);
}
I've always thought that with WPF, your application is the DataContext, while the UI objects like Buttons, ListBoxes, TextBoxes, etc are simply a pretty layer that sits on top of the DataContext to allow the User to interact with it.
In the XAML, set the Tag property to the current item.
In the click handler, cast it back.
Usernames user = (sender as Button).Tag as Usernames;
To bind a datacollection it is often easiest to use an ObservableCollection (if the data is changing runtime). When you do the binding you have to define a datacontext, a datasoure and a datapath. I will advice you to read some more about binding on MSDN :D
This will work for you -
MessageBox.Show(((sender as Button).DataContext as UserNames).UserName);

WPF - Extend ListView with checkable AND selectable ListViewItems

I already read many examples on extending ListViews with checkboxes bound with IsSelected. But I want something more.
I want a seperation between the checked and selected state, so i get a ListBox that has a single selected item, but can have multiple checked items.
Unfortunately ListViewItem does not have a property for checked and I dont see a possibility to get the ListView to work with a custom CheckableListViewItem.
Of course i could use a List of objects with a checked property as ItemSource, but I dont think thats a good way to go. Checked or not is a matter of the list or item-container, not of the object listed in it. Beside that I dont want all my classes like user, role, group to have counterparts like checkableUser, checkableRole and checkableGroup.
The behaviour i want can be easyly accomblished for the UI with a
<DataTemplate x:Key="CheckBoxCell">
<StackPanel Orientation="Horizontal">
<CheckBox />
</StackPanel>
</DataTemplate>
and a
<GridViewColumn CellTemplate="{StaticResource CheckBoxCell}" Width="30"/>
But without a binding on the checkbox i cant check if it is checked or not.
Is there any way to accomplish something like that? The perfect solution for me would be to have listView1.SelectedItem, listView1.CheckedItems and maybe a listView1.UncheckedItems and of course listView1.CheckItem and listView1.UncheckItem.
Thanks for any help.
Ok, I got it.
Wasn't much to do, but becouse I'm new to the whole WPF stuff, its been some work to figure out.
Here is the solution:
public class CheckableListViewItem : ListViewItem
{
[Category("Appearance")]
[Bindable(true)]
public bool IsChecked { get; set; }
}
public class CheckableListView : ListView
{
public IList CheckedItems
{
get
{
List<object> CheckedItems = new List<object>();
for (int i=0;i < this.Items.Count; ++i)
{
if ((this.ItemContainerGenerator.ContainerFromIndex(i) as CheckableListViewItem).IsChecked)
CheckedItems.Add(this.Items[i]);
}
return CheckedItems;
}
}
public bool IsChecked(int index)
{
if (index < this.Items.Count) return (this.ItemContainerGenerator.ContainerFromIndex(index) as CheckableListViewItem).IsChecked;
else throw new IndexOutOfRangeException();
}
protected override bool IsItemItsOwnContainerOverride(object item)
{
if (item is CheckableListViewItem) return true;
else return false;
}
protected override DependencyObject GetContainerForItemOverride()
{
return new CheckableListViewItem();
}
}
Insert into your XAML under Window.Resources (clr = my class namespace):
<DataTemplate x:Key="CheckBoxCell">
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked="{Binding Path=IsChecked,
RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type clr:CheckableListViewItem}}}" />
</StackPanel>
</DataTemplate>
And this as your CheckableListView:
<clr:CheckableListView SelectionMode="Single" [...] >
<ListView.View>
<GridView>
<GridViewColumn CellTemplate="{StaticResource CheckBoxCell}"
Width="30"/>
[...]
</GridView>
</ListView.View>
</clr:CheckableListView>
Maybe this helps someone with the same problem.
In order to do this, you will have to create a custom ListBox and custom ListBoxItem controls to use within your application. Otherwise, you would have to add it to the items in your lists as a generic object ICheckable<T> (where T is User or Role) and have an ICheckableCollection<ICheckable<T>> for your items instead of adding a checkable to your model objects.

Resources