I want to create a Listbox from where it's possible to select elements with checkboxes. It gets the elements through data-binding from a database. The items appear in the Listbox, but when I send the form, the code-behind doesn't receive a SelectedItem value.
The XAML section for the listbox looks like this:
<Grid x:Name="grMozik" Visibility="Visible" Margin="0,0,0,0" DataContext="{Binding}" Grid.Row="3" Grid.ColumnSpan="2">
<ListBox Name="lbMozik" Margin="15" Width="300" Height="200" ItemsSource="{Binding}">
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Focusable" Value="False"/>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding MoziNeve}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
And for test purposes the code that would show the selected item looks like this:
string text = ((ListBoxItem)lbMozik.SelectedItem).Content.ToString();
MessageBox.Show(text2);
ListBox.SelectedItem comes from a ListBoxItem which has IsSelected property set to true. If you want to select by CheckBoxes, then bind each of them to owner ListBoxItem.IsSelected:
<CheckBox Content="{Binding MoziNeve}"
IsChecked="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=ListBoxItem}}"/>
Related
I have a ListBox with its ItemsSource bound to some UserControl-s and shown based on their current states(IsVisible)
Here is the code
<ListBox x:Name="sidebarList" Margin="0,0,10,10" ItemsSource="{Binding Modules, Mode=TwoWay}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0 5 0 5" Visibility="{Binding IsVisible, Mode=TwoWay}">
<TextBlock Text="{Binding Title}" FontWeight="Bold" />
<TextBlock Margin="0 5 0 0" MaxWidth="200" Foreground="Gray" Text="{Binding Detail}"
TextWrapping="WrapWithOverflow">
</TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsVisible}" Value="Collapsed">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
And now I'm trying to only get "IsVisible"/selected parts when a button is pressed. As of right now, the ListBox actually contains every option but just showing the IsVisible ones(at least that's what I think).
How do I only get the selected options? I have tried to use a new List with the same type as the UserControl-s type(which I placed in app.xaml.cs to call from anywhere) and add to that list when their state changes to IsVisible
but the List doesn't show up in my classes where I check them.
Sounds like what you really need is a view-model. Bind your Listbox to a view model that has an observable collection that only shows view-models of the items you want to present.
I can give you a more "correct" answer about how to do it with style/data-triggers but you should really just learn about MVVM and use a view-model to simplify.
I have a TabControl which is bound to a List of UserControls (MyControls)
<TabControl Background="{x:Null}" x:Name="MyView" ItemsSource="{Binding MyControls}" >
I want to bind the header of each tab item to a property(Title) in each UserControl. Which I did as below
<TabControl.ItemContainerStyle>
<Style TargetType="TabItem">
<Setter Property="Header" Value="{Binding Title}"/>
</Style>
</TabControl.ItemContainerStyle>
However since I override the ItemContainerStyle I lost all the default style for the application. My tab header looks different from other tab headers in the application
Is there any way to just bind to the Title without changing any style?
Define an ItemTemplate:
<TabControl Background="{x:Null}" x:Name="MyView" ItemsSource="{Binding MyControls}">
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Title}" />
</DataTemplate>
</TabControl.ItemTemplate>
</TabControl>
MyControls shouldn't return an IEnumerable<UserControl> though. It should return an IEnumerable<YourObject> where YourObject is a POCO class with a Title property along with any other properties. You should then use DataTemplates to define the appearance of a YourObject.
I need to show a default text in my ComboBox, this text must not changed also when the user select an item of the Combobox, actually for do this I've created this structure:
<ComboBox ItemsSource="{Binding AvailableNations}" Width="160" Height="55" Margin="0, 0, 0, 15"
Text="Select Countries" IsEditable="True">
<ComboBox.ItemTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding IsChecked}" Content="{Binding Item.Name}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
this display as default text Select Countries but if I select an item the default text will disappear and the item selected will be displayed, how can I fix this?
You could use a Combined Template (ref post)
<Window.Resources>
<ResourceDictionary>
<DataTemplate x:Key="NormalItemTemplate" >
<CheckBox IsChecked="{Binding IsChecked}" Content="{Binding Item.Name}" />
</DataTemplate>
<DataTemplate x:Key="SelectionBoxTemplate" >
<TextBlock>Select Countries</TextBlock>
</DataTemplate>
<DataTemplate x:Key="CombinedTemplate">
<ContentPresenter x:Name="Presenter"
Content="{Binding}"
ContentTemplate="{StaticResource NormalItemTemplate}" />
<DataTemplate.Triggers>
<DataTrigger
Binding="{Binding RelativeSource={RelativeSource FindAncestor,ComboBoxItem,1}}"
Value="{x:Null}">
<Setter TargetName="Presenter" Property="ContentTemplate"
Value="{StaticResource SelectionBoxTemplate}" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ResourceDictionary>
</Window.Resources>
<Grid>
<ComboBox ItemsSource="{Binding AvailableNations}"
SelectedItem="{Binding SelectedNation}"
ItemTemplate="{StaticResource CombinedTemplate}"
Width="160" Height="55" Margin="0, 0, 0, 15" >
</ComboBox>
</Grid>
The way it works is described in the original answer. Note that the suggested solution will only work when IsEditable is set to false, I assume that won't be a problem in your case. Second, to get the text displayed at start up I bound SelectedItem (e.g. to the first item in the collection).
From the comments, it sounds like you just want the Select Countries text to display at all times, even when an item is selected.
Personally I would just go the simple route and place a TextBox on top of the ComboBox, and hide the Display Text of the ComboBox by using a Transparent Foreground color.
Here's a quick example demonstrating it :
<Grid>
<ComboBox SelectedIndex="1" Foreground="Transparent">
<ComboBox.Resources>
<Style TargetType="{x:Type ComboBoxItem}">
<!-- Make sure ComboBoxItems don't have transparent text -->
<Setter Property="Foreground" Value="{StaticResource {x:Static SystemColors.ControlTextBrushKey}}" />
</Style>
</ComboBox.Resources>
<ComboBoxItem>Test 1</ComboBoxItem>
<ComboBoxItem>Test 2</ComboBoxItem>
<ComboBoxItem>Test 3</ComboBoxItem>
</ComboBox>
<TextBlock Text="Select Countries" Margin="4,3" IsHitTestVisible="False" />
</Grid>
And the results (note that SelectedIndex = 1)
I'm sure there's other ways too, such as overwriting the way it paints the display text, or changing the control template, but this seemed like the easiest to me.
I have this xaml. And I need to uncheck all other checkboxes where one is checked. I other words to allow to check only one. I add TreeViewItems on a runtime.
<TreeView Name="treeView_max" >
<TreeView.Resources>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel Orientation="Horizontal" >
<CheckBox Name="chk" Margin="2" Tag="{Binding}" Checked="checkBox_Checked">
</CheckBox>
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</TreeView.Resources>
</TreeView>
Adding TreeViewItems at runtime:
foreach (Genesyslab.Desktop.Modules.Core.Model.BusinessAttributes.IDispositionCodeValue item in listOfDispositionCodeValueItemsControl.Items)
{
TreeViewItem newChild2 = new TreeViewItem();
newChild2.Header = item.DisplayName.Remove(0,item.DisplayName.IndexOf("-") + 1);
treeView_max.Items.Add(newChild2);..........`
and
private void checkBox_Checked(object sender, RoutedEventArgs e)
{
try
{
//uncheck all checkboxes except selected one
}
catch (Exception es)
{
MessageBox.Show(es.ToString());
}
}
You can use RadioButton controls that belong to the same group instead, which will get you the behavior of only one option being able to be selected at a time.
Then edit the control template to display CheckBox controls in place of those RadioButton's, and bind the IsChecked property of each CheckBox to its parent RadioButton. Now when you "check" a CheckBox, all other CheckBox controls will become unchecked.
<TreeView Name="treeView_max" >
<TreeView.Resources>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel Orientation="Horizontal" >
<RadioButton Name="chk" Margin="2" Tag="{Binding}" GroupName="SomeGroup">
<RadioButton.Template>
<ControlTemplate>
<CheckBox IsChecked="{Binding IsChecked, Mode=TwoWay, RelativeSource={RelativeSource AncestorType=RadioButton}}" />
</ControlTemplate>
</RadioButton.Template>
</RadioButton>
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</TreeView.Resources>
</TreeView>
Be careful about where you use this. Users are used to seeing RadioButton's when they're only able to select one option, and CheckBox's where they can select multiple options.
I have ComboBox with custom ItemTemplate.
<ComboBox Height="20" Width="200"
SelectedItem="{Binding Path=SelectedDesign}"
ItemsSource="{Binding Path=Designs}" HorizontalAlignment="Left"
ScrollViewer.CanContentScroll="False">
<ComboBox.ItemTemplate>
<DataTemplate DataType="{x:Type formdesign:FormDesignContainer}">
<Rectangle Width="200" Height="100">
<Rectangle.Fill>
<ImageBrush ImageSource="{Binding Path=ImageThumb}" Stretch="Uniform" />
</Rectangle.Fill>
</Rectangle>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
This works well. However WPF tries to draw rectangle as Combobox Text. How can I set "text" for this template. By "text" I mean string or control which represent selected item and write into combobox when item is selected
In other words I'd like to do this:
But now I got this
Try setting SelectionBoxItemTemplate with a TextBlock.
Appears that SelectionBoxItemTemplate is read-only. So another approach is to override ItemContainerStyle.Template. Example
I found this solution by Ray Burns a good approach. You can define two DataTemplate one for Items in the drop down list and the other for the selected item which should be shown in the Combobox. The using a trigger and checking the visual tree it decide which one to use.
<Window.Resources>
<DataTemplate x:Key="NormalItemTemplate" ...>
...
</DataTemplate>
<DataTemplate x:Key="SelectionBoxTemplate" ...>
...
</DataTemplate>
<DataTemplate x:Key="CombinedTemplate">
<ContentPresenter x:Name="Presenter"
Content="{Binding}"
ContentTemplate="{StaticResource NormalItemTemplate}" />
<DataTemplate.Triggers>
<DataTrigger
Binding="{Binding RelativeSource={RelativeSource FindAncestor,ComboBoxItem,1}}"
Value="{x:Null}">
<Setter TargetName="Presenter" Property="ContentTemplate"
Value="{StaticResource SelectionBoxTemplate}" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</Window.Resources>
...
<ComboBox
ItemTemplate="{StaticResource CombinedTemplate}"
ItemsSource="..."/>
Add Textblock to the datatemplate and bind it
or add Contentpersenter on the rectangle
Edit:
it seems like i didn't got what you were tring to accomplish ,