I have a TabControl that creates the TabItems from a ObservableCollection.
So in my ViewModel I already have a boolean Property IsMultiple and already gets set in code. So how do I hide the Tab header completely, but still display the content of that tab.
I have this:
<TabControl ItemsSource="{Binding myObservableCollection}"
ItemContainerStyle="{StaticResource myTabItemStyle}"
Style="{StaticResource myTabStyle}">
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding myTabHeaderTextProperty}" />
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
<DataTemplate>
</TabControl.ContentTemplate>
Basically I want to hide the itemtemplate, note that I cant just hide the TextBlock, because the style then still is there only with empty text. I want to remove/Hide the complete Tab header.
Set the Visibility property of the ItemContainerStyle to Collapsed:
<TabControl ItemsSource="{Binding myObservableCollection}">
<TabControl.ItemContainerStyle>
<Style TargetType="TabItem">
<Setter Property="Visibility" Value="Collapsed" />
</Style>
</TabControl.ItemContainerStyle>
<TabControl.ContentTemplate>
<DataTemplate>
<TextBlock>content...</TextBlock>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
Related
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}}"/>
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.
Basically I'm having two related problems:
1) The same problem as in this question How do I make an ItemsControl stretch to fill all availible space?, basically the ItemsControl doesn't fill in the whole space and the provided solution with DockedPanel doesn't work for me, because I need the items to stack vertically and not horizontally. Is there any other way to achieve this than using complex dynamic Grids?
2) There seems to be something off with the way DataGrid is presented when I'm using the method in this question WPF MVVM Multiple ContentControls in TabControl.
The headers are for some reason crushed to the side, also adding info to the table makes it look very bad. This wouldn't normally happen if I wasn't using this method of ItemsControl to display the table.
Code for TabControl:
<TabControl ItemsSource="{Binding Tabs}">
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Header}"/>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
<ItemsControl ItemsSource="{Binding Content}"/>
</ScrollViewer>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
Code for DataGrid that is in the UserControl (view.xaml) which is bound to the above TabControl:
<DataGrid Grid.Row="0" Margin="10 10 10 0" ItemsSource="{Binding List}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTemplateColumn Header="ID">
<DataGridTemplateColumn.HeaderStyle>
<Style TargetType="DataGridColumnHeader">
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
</Style>
</DataGridTemplateColumn.HeaderStyle>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Label Content="{Binding Path=Id}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
//...
//Same for other columns
//...
</DataGrid>
Removing Header style does not help.
Remove the ScrollViewer element from your ContentTemplate. The DataGrid has its own ScrollViewer element built-in into its default ControlTemplate.
I actually found the answer and the accepted answer is correct (there's a workaround):
WPF ScrollViewer around DataGrid affects column width
As for my first question, I just sticked to UniformGrid and binded its row count to the ViewModel.
I have two ItemsControls with the same ItemsSource. One has some controls for each item, the other has a checkbox for each item. The controls in them are dynamically added. How can I bind the visibility of the first ItemsControls to the corresponding checkbox in the other ItemsControls ?
Here's the first ItemsControl containing multiple TextBlocks in the row. Note: I want to hide the whole row of controls.
<ItemsControl ItemsSource="{Binding VehicleCollection}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<TextBlock />
<TextBlock />
<TextBlock />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Here's the second ItemsControl with the checkboxes:
<ItemsControl ItemsSource="{Binding VehicleCollection}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<CheckBox Content="{Binding Name}"
IsChecked="True" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
So what happens is, for each item in VehicleCollection, a new row of textblocks is added for the first ItemsControl, and a checkbox is added for the second ItemsControl. These should relate to each other for example: If I uncheck the first checkbox, the first row for the other ItemsControl should be hidden.
I know how to do the booltovis converter, just not sure on how to relate these two ItemsControls.
Edit: These are both in the mainwindow.xaml by the way.
In order to show or hide an item of the first ItemsControl, add an IsVisible property to your Vehicle class (i.e. the element type of the VehicleCollection) and bind the Visibility of the item's ContentPresenter to the IsVisible property in an ItemContainerStyle:
<ItemsControl ItemsSource="{Binding VehicleCollection}">
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Visibility"
Value="{Binding IsVisible,
Converter={StaticResource BooleanToVisibilityConverter}}"/>
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
...
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
In the other ItemsControl, bind the IsChecked property of the CheckBox to the IsVisible property:
<ItemsControl ItemsSource="{Binding VehicleCollection}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Name}" IsChecked="{Binding IsVisible}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Of course make sure that class Vehicle implements INotifyPropertyChanged and fires the PropertyChanged event when the IsVisible property changes.
You should be able to manage this by adding a boolean Property in your Vehicle class, which I presume is the basis for your VehicleCollection. Something like: IsSelected.
Then you can modify your XAML as shown below:
<ItemsControl ItemsSource="{Binding VehicleCollection}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<TextBlock Visibility="{Binding IsSelected,Converter={StaticResource boolToVisConverter}}"/>
<TextBlock Visibility="{Binding IsSelected,Converter={StaticResource boolToVisConverter}}"/>
<TextBlock Visibility="{Binding IsSelected,Converter={StaticResource boolToVisConverter}}"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<ItemsControl ItemsSource="{Binding VehicleCollection}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<CheckBox Content="{Binding Name}"
IsChecked="{Binding IsSelected}" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
This is untested XAML, as I just typed it into the answer. Might need a tweak.
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 ,