I'm developing a CheckedListBox with self removable ListBoxItems. The problem is that an item only gets checked if the user clicks on the CheckBox area, which is kind of awkward.
How do I create ListBoxItem triggers (IsSelected) to check the checkboxes on a "DataSourced" ListBox? Eg:
Below is my control (all other code have been omitted for brevity):
<ListBox x:Name="executors" ItemsSource="{Binding Executors}" HorizontalAlignment="Left" Height="121" Margin="23,19,0,0" VerticalAlignment="Top" Width="362">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Height" Value="30" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="30" />
</Grid.ColumnDefinitions>
<CheckBox Margin="4,8" IsChecked="{Binding Enabled}">
<ContentPresenter Content="{Binding Description}">
</ContentPresenter>
</CheckBox>
<Button Command="{Binding DataContext.RemoveExecutorCommand, ElementName=executors}" CommandParameter="{Binding}" Background="White" Height="22" Width="22" Grid.Column="1">
<Image Source="trash.png" Stretch="Fill" Width="14" Height="14" />
</Button>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
Executors is a ObservableCollection of Executor which has Enabled and Description as members.
For further reference for those who come across this same question, here's a working snippet I have done. I couldn't find any working sample anywhere, so this might be of much use.
The main idea here was to either propagate the selection event to the CheckBoxes, which sounds too much of a work, or to simple extend the CheckBox selection area to fit the ListBoxItem.
Below is a sample on how to achieve the second option:
<ListBox x:Name="executors" ItemsSource="{Binding Executors}" HorizontalAlignment="Left" Height="121" Margin="23,19,0,0" VerticalAlignment="Top" Width="362" ScrollViewer.VerticalScrollBarVisibility="Visible">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Height" Value="30"/>
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="9*"/>
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<CheckBox Content="{Binding Description}" IsChecked="{Binding Enabled}" VerticalContentAlignment="Center" Margin="4,0"/>
<Button Command="{Binding DataContext.RemoveExecutorCommand, ElementName=executors}" CommandParameter="{Binding}" Width="21" Height="21" Background="White" Grid.Column="1">
<Image Source="trash.png" Stretch="Fill" Width="14" Height="14" />
</Button>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
This should produce the following:
Related
I have a code like this:
<ListBox Name="lstBox"
ItemsSource="{Binding ViewModelsView}"
SelectedItem="{Binding SelectedAlertViewOutput, Mode=OneWayToSource}">
<ListBox.Style>
<Style TargetType="{x:Type ListBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBox}">
<Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}"
Background="{TemplateBinding Background}" Padding="1" >
<ScrollViewer Padding="{TemplateBinding Padding}" >
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</ScrollViewer>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemContainerStyle">
<Setter.Value>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="IsSelected"
Value="{Binding AlertRecord.IsSelected, Mode=TwoWay}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Grid HorizontalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<controls:AlertExpander
Margin="1"
Value="{Binding AlertRecord.AlertCategory}"
IsExpanded="{Binding Path=IsSelected, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"
IsActive="{Binding AlertRecord.IsActive, Mode=OneWay }"
StartTime="{Binding AlertRecord.Timestamp, Mode=OneWay}"
StopTime="{Binding AlertRecord.EndTimestamp, Mode=OneWay}"
AlertId="{Binding AlertRecord.Id, Mode=OneWay}"
<controls:AlertExpander.Content>
<ContentPresenter>
</ContentPresenter>
</controls:AlertExpander.Content>
</controls:AlertExpander>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.Style>
<ListBox.Resources>
<DataTemplate DataType="{x:Type local:AlertUnknownViewModel}">
<local:AlertUnknownView></local:AlertUnknownView>
</DataTemplate>
</ListBox.Resources>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="4">
<ContentPresenter Content="{Binding}"></ContentPresenter>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
ListBox uses my control AlertExpander as ListBoxItem.
Is it possible to create a list consisting not only of elements of type AlertExpander? I would like for an element of another type to also use the parameters on which AlertExpander depends.
I have several types of controls that accept the same parameters as AlertExpander, but look different, and I need to display elements of all types in the list, not just AlertExpander.
AlertExpander.xaml:
<Expander
<Control.Style>
<Style TargetType="Expander">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Expander">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- Header -->
<ToggleButton Name="HeaderButton">
<ToggleButton.Style>
<Style TargetType="ToggleButton">
<Setter Property="IsChecked" Value="{Binding IsExpanded, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}, UpdateSourceTrigger=PropertyChanged}"/>
<Setter Property="IsEnabled" Value="{Binding Path=Expandable, RelativeSource={RelativeSource AncestorType=controls:AlertExpander}}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Grid>
<Border Grid.Row="1" BorderThickness="1" BorderBrush="Black"
CornerRadius="{Binding BorderCornerRadius, RelativeSource={RelativeSource AncestorType=controls:AlertExpander}, Mode=OneWay}">
</Border>
<!-- Border shade -->
<Border Name="BorderShade" Grid.Row="1" BorderThickness="1" BorderBrush="Transparent" Visibility="Collapsed"
</Border>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image Grid.RowSpan="2" Margin="10">
<Image.OpacityMask>
<ImageBrush ImageSource="{Binding SelectedItem.IconSource, RelativeSource={RelativeSource AncestorType=controls:AlertExpander}, Mode=OneWay}"/>
</Image.OpacityMask>
<Image.Source>
<MultiBinding Mode="OneWay" Converter="{converters:GrayscaleImageSourceConverter}">
<Binding Path="SelectedItem" RelativeSource="{RelativeSource AncestorType=controls:AlertExpander}"/>
<Binding Path="IsActive" RelativeSource="{RelativeSource AncestorType=controls:AlertExpander}"/>
</MultiBinding>
</Image.Source>
</Image>
<StackPanel x:Name="topHeader" Grid.Row="0" Grid.Column="1" Orientation="Horizontal" VerticalAlignment="Bottom">
</StackPanel>
<Label x:Name="bottomHeader" Grid.Row="1" Grid.Column="1" VerticalAlignment="Top" Background="Transparent" Padding="0,2,0,0" FontSize="9pt"
Content="{Binding AlertHeaderTime, RelativeSource={RelativeSource AncestorType=controls:AlertExpander}, Mode=OneWay}">
</Label>
</Grid>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter TargetName="BorderShade" Property="Visibility" Value="Visible"/>
</Trigger>
<DataTrigger Binding="{Binding IsAlertHeaderTimeShown, RelativeSource={RelativeSource AncestorType=controls:AlertExpander}, Mode=OneWay}" Value="false">
<Setter TargetName="topHeader" Property="VerticalAlignment" Value="Center"/>
<Setter TargetName="topHeader" Property="Grid.RowSpan" Value="2"/>
<Setter TargetName="bottomHeader" Property="Visibility" Value="Hidden"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsChecked" Value="true">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Grid>
<Border Grid.Row="1" BorderThickness="1" BorderBrush="Black"
CornerRadius="{Binding BorderCornerRadius, RelativeSource={RelativeSource AncestorType=controls:AlertExpander}, Mode=OneWay, Converter={converters:AlertExpanderCornerRadiusTopConverter}}">
</Border>
<!-- Border shade -->
<Border Name="BorderShade" Grid.Row="1" BorderThickness="1" BorderBrush="Transparent" Visibility="Collapsed"
Background="{Binding MouseOverShade, RelativeSource={RelativeSource AncestorType=controls:AlertExpander}, Mode=OneWay}"
CornerRadius="{Binding BorderCornerRadius, RelativeSource={RelativeSource AncestorType=controls:AlertExpander}, Mode=OneWay, Converter={converters:AlertExpanderCornerRadiusTopConverter}}">
</Border>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image Grid.RowSpan="2" Margin="10">
<Image.OpacityMask>
<ImageBrush ImageSource="{Binding SelectedItem.IconSource, RelativeSource={RelativeSource AncestorType=controls:AlertExpander}, Mode=OneWay}"/>
</Image.OpacityMask>
<Image.Source>
<MultiBinding Mode="OneWay" Converter="{converters:GrayscaleImageSourceConverter}">
<Binding Path="SelectedItem" RelativeSource="{RelativeSource AncestorType=controls:AlertExpander}"/>
<Binding Path="IsActive" RelativeSource="{RelativeSource AncestorType=controls:AlertExpander}"/>
</MultiBinding>
</Image.Source>
</Image>
<StackPanel x:Name="topHeader" Grid.Row="0" Grid.Column="1" Orientation="Horizontal" VerticalAlignment="Bottom">
<Label Background="Transparent" Padding="0,0,0,2" FontSize="12pt"
FontWeight="{Binding IsActive, Mode=OneWay, RelativeSource={RelativeSource AncestorType=controls:AlertExpander}, Converter={converters:BoolToFontWeightConverter}}"
Content="{Binding AlertHeader, RelativeSource={RelativeSource AncestorType=controls:AlertExpander}, Mode=OneWay}">
</Label>
<Label Background="Transparent" Padding="4,0,0,2" FontSize="12pt"
FontWeight="{Binding IsActive, Mode=OneWay, RelativeSource={RelativeSource AncestorType=controls:AlertExpander}, Converter={converters:BoolToFontWeightConverter}}"
Visibility="{Binding IsActive, Mode=OneWay, RelativeSource={RelativeSource AncestorType=controls:AlertExpander}, Converter={converters:InactiveNoteVisibilityConverter}}"
Content="{Binding InactiveNote, RelativeSource={RelativeSource AncestorType=controls:AlertExpander}, Mode=OneWay}">
</Label>
</StackPanel>
<Label x:Name="bottomHeader" Grid.Row="1" Grid.Column="1" VerticalAlignment="Top" Background="Transparent" Padding="0,2,0,0" FontSize="9pt"
Content="{Binding AlertHeaderTime, RelativeSource={RelativeSource AncestorType=controls:AlertExpander}, Mode=OneWay}">
</Label>
</Grid>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter TargetName="BorderShade" Property="Visibility" Value="Visible"/>
</Trigger>
<DataTrigger Binding="{Binding IsAlertHeaderTimeShown, RelativeSource={RelativeSource AncestorType=controls:AlertExpander}, Mode=OneWay}" Value="false">
<Setter TargetName="topHeader" Property="VerticalAlignment" Value="Center"/>
<Setter TargetName="topHeader" Property="Grid.RowSpan" Value="2"/>
<Setter TargetName="bottomHeader" Property="Visibility" Value="Hidden"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</ToggleButton.Style>
</ToggleButton>
<!-- Content -->
<ScrollViewer Name="ContentScrollViewer" Grid.Row="1"
HorizontalScrollBarVisibility="Hidden"
VerticalScrollBarVisibility="Hidden"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Bottom"
Visibility="Visible">
<Border Name="ExpanderContentBorder" BorderThickness="1,0,1,1" BorderBrush="Black">
<ContentPresenter ContentSource="Content"/>
</Border>
</ScrollViewer>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Control.Style>
enter image description here
Before I get to the code, I want to point out that this is a job for data templates, rather than control templates.
The Template property takes a ControlTemplate and is used to define the structure of a control. This is usually used when you are building a control from scratch or significantly altering one. What you want to do is just change how your data is being displayed inside an existing control. For that, there are DataTemplate properties, such as ItemTemplate.
With that out of the way, I put together some code for you that should at least point you in the right direction:
<ListBox Name="lstBox" ItemsSource="{Binding ViewModelsView}" SelectedItem="{Binding SelectedAlertViewOutput, Mode=OneWayToSource}">
<ListBox.Resources>
<DataTemplate DataType="local:AlertRecord" x:Key="AlertExpanderItem">
<controls:AlertExpander Margin="1"
Value="{Binding AlertCategory}"
IsExpanded="{Binding IsSelected, Mode=TwoWay}"
IsActive="{Binding IsActive, Mode=OneWay }"
StartTime="{Binding Timestamp, Mode=OneWay}"
StopTime="{Binding EndTimestamp, Mode=OneWay}"
AlertId="{Binding Id, Mode=OneWay}"/>
</DataTemplate>
<DataTemplate DataType="local:AlertRecord" x:Key="OtherControlItem">
<controls:OtherControl Margin="1"
Value="{Binding AlertCategory}"
IsExpanded="{Binding IsSelected, Mode=TwoWay}"
IsActive="{Binding IsActive, Mode=OneWay }"
StartTime="{Binding Timestamp, Mode=OneWay}"
StopTime="{Binding EndTimestamp, Mode=OneWay}"
AlertId="{Binding Id, Mode=OneWay}"/>
</DataTemplate>
</ListBox.Resources>
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}"/>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<ContentControl Content="{Binding}">
<ContentControl.Style>
<Style TargetType="ContentControl">
<Setter Property="ContentTemplate" Value="{StaticResource OtherControlItem}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Value}" Value="0">
<Setter Property="ContentTemplate" Value="{StaticResource AlertExpanderItem}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
...
public class AlertRecord
{
...
public bool HasPositiveValue { get { return Value >= 0 } }
...
}
I start by defining two different ItemTemplates inside inside the Resources of the ListBox. You would define one for each of the different controls you need to use. Notice that I left off "AlertRecord." from the bindings. That is because each DataTemplate instance will have the AlertRecord as its DataContext.
For the ItemTemplate property, I borrowed from this answer here: https://stackoverflow.com/a/10191762/5086631. I made a DataTemplate with a ContentControl and used the Style to change the ContentTemplate based on DataTriggers. This lets you change the template based on the properties of your list item.
Based on your comment, the style is set up so that "OtherControlItem" (the non-expander control) is used by default, and AlertExpanderItem is used when HasPositiveValue returns true. HasPositiveValue is a property you would need to add to AlertRecord.
I needed to implement a third party solution for a vitalizing warp panel. The first two I tried didn't work because of this error message:
' ...should not return PositiveInfinity as its DesiredSize, even if
Infinity is passed in as available size.'
So next I went to a commercial solution which gave me the exact same error. So clearly there is something wrong with my code. But no matter what I try, the problem persists. To note, I tried the last solution with a basic example and that did indeed work.
I presume that one of my controls are the problem, perhaps needing to stipulate the dimensions, but, I have tried that on every relevant control. Below is the code. It is a ListBox inside a Grid using a data template.
<Grid x:Name="MainGrid" Background="#222">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="40" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="300" MinWidth="200" MaxWidth="400" />
<ColumnDefinition Width="*" MinWidth="200" />
<ColumnDefinition Width="400" MinWidth="270" MaxWidth="600" />
</Grid.ColumnDefinitions>
...
<!--#region Main Library Column-->
<ListBox x:Name="LibraryBox"
Grid.Column="1"
Grid.Row="0"
Grid.RowSpan="4"
Margin="20,10,20,10"
BorderBrush="Transparent"
Background="#1e1e1e"
ItemsSource="{Binding}"
ItemContainerStyle="{StaticResource ListBoxItemStyle}"
IsSynchronizedWithCurrentItem="True"
VirtualizingPanel.IsVirtualizing="True"
VirtualizingPanel.IsVirtualizingWhenGrouping="True"
VirtualizingPanel.IsContainerVirtualizable="True"
VirtualizingPanel.CacheLengthUnit="Page"
VirtualizingPanel.CacheLength="1,2"
VirtualizingPanel.VirtualizationMode="Standard"
VirtualizingPanel.ScrollUnit="Pixel"
ScrollViewer.IsDeferredScrollingEnabled="False"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
SelectionMode="Extended"
SelectionChanged="LibraryBox_SelectionChanged"
MouseDoubleClick="LibraryBox_MouseDoubleClick">
<ListBox.Resources>
<!--#region scrollbar style-->
<Style TargetType="{x:Type ScrollBar}">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Foreground" Value="#990000"/>
<Setter Property="Width" Value="25"/>
</Style>
<!--#region Not working...-->
<Style TargetType="{x:Type RepeatButton}">
<Setter Property="Background" Value="AliceBlue"/>
<Setter Property="Foreground" Value="Transparent"/>
<Setter Property="Width" Value="40"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RepeatButton}">
<Border Background="Red" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!--#endregion-->
<!--#endregion-->
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Red"/>
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Red"/>
</ListBox.Resources>
<ListBox.ContextMenu>
<ContextMenu>
<MenuItem Header="Edit" Click="ContextMenuItemEdit_Click"/>
<MenuItem Header="ComicVine Scraper" Click="MenuItemScraper_Click"/>
<Separator/>
<MenuItem Header="Delete" Click="ContextMenuItemDelete_Click"/>
</ContextMenu>
</ListBox.ContextMenu>
<!--#region Group Style-->
<ListBox.GroupStyle>
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Expander IsExpanded="True">
<Expander.Header>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}"
FontWeight="Bold"
Foreground="#dbdbdb"
FontSize="16"
FontFamily="Cordia New"
VerticalAlignment="Bottom" />
<TextBlock Text="{Binding ItemCount}"
FontSize="16"
Foreground="#dbdbdb"
FontStyle="Italic"
Margin="10,0,0,0"
FontFamily="Cordia New"
VerticalAlignment="Bottom" />
</StackPanel>
</Expander.Header>
<ItemsPresenter />
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</ListBox.GroupStyle>
<!--#endregion-->
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<Viewbox Height="100" Width="70" Margin="2">
<Viewbox.LayoutTransform>
<ScaleTransform ScaleX="{Binding Value, ElementName=ZoomSlider}"
ScaleY="{Binding Value, ElementName=ZoomSlider}"/>
</Viewbox.LayoutTransform>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="300"/>
<ColumnDefinition Width="32"/>
</Grid.ColumnDefinitions>
<!--This is for thumbnails-->
<Image x:Name="coverImage"
Grid.Column="0"
Grid.Row="0"
Source="{Binding CoverPath, Converter={StaticResource UriToBitmapConverter}, IsAsync=True}"/>
<Rectangle x:Name="ReadMarkerBottom"
Grid.Column="1"
Grid.Row="1"
Margin="-16,0,0,0"
Fill="#fff"
Width="32"
Height="32"
Loaded="CoverImage_Loaded"/>
<Rectangle x:Name="ReadMarkerTop"
Grid.Column="1"
Grid.Row="1"
Margin="-16,0,0,0"
Fill="#000"
Width="30"
Height="30"
Loaded="CoverImage_Loaded"/>
</Grid>
</Viewbox>
<TextBlock TextTrimming="CharacterEllipsis"
TextAlignment="Center"
Width="120"
Foreground="#dbdbdb"
Background="Transparent"
Margin="0,0,0,5"
Loaded="Text_Loaded"
FontFamily="Cordia New"
FontWeight="Bold">
</TextBlock>
<TextBlock TextTrimming="CharacterEllipsis"
TextAlignment="Center"
Width="120"
Foreground="#dbdbdb"
Background="Transparent"
Margin="0,0,0,5"
Loaded="IssueNumer_Loaded"
FontFamily="Cordia New"/>
<TextBlock TextTrimming="CharacterEllipsis"
TextAlignment="Center"
Width="120"
Foreground="#dbdbdb"
Background="Transparent"
Margin="0,0,0,5"
Loaded="CountStack_Loaded"
FontFamily="Cordia New"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<extendedPanelControls:BinaryVirtualizingWrapPanel
AutoUpdateViewportOnDetectingTransactionalUpdatesToDataSource="True"
ItemPositioningMode="Greedy"
IsItemsHost="True"
Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
<!--#endregion-->
The answer was to set the MaxHeight on the <ItemsPresenter /> inside the GroupStyle so it new it was not going to go on forever
I've formatted a ComboBox to display each item's details, please don't take the design as final, it's just an example:
But as you can see, the displayed item (Inside the box with the arrow) is broken:
So I need to format that component too, to display only the Server value in that box. I've tried to find the correct element, and even managed to find a way to reformat the whole combo box, but no way to add a template for the data display inside that box.
How do I edit the data template for that container? This is the result I'd expect:
<ComboBox x:Name="cboSourceMySql" Grid.Column="1" Margin="5,0,5,0" ItemsSource="{Binding OdbcDataSources, Mode=TwoWay}" Grid.Row="1" >
<ComboBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="50" />
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<Label Content="Server:" Grid.Column="0" Grid.Row="0" />
<TextBlock Text="{Binding Server}" VerticalAlignment="Center" Grid.Column="1" Grid.Row="0" />
<Label Content="Driver:" Grid.Column="0" Grid.Row="1" />
<TextBlock Text="{Binding Driver}" VerticalAlignment="Center" Grid.Column="1" Grid.Row="1" />
</Grid>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
From the article WPF Combobox: Different template in textbox and drop-downlist
I think you can use the below style
<ComboBox
x:Name="cboSourceMySql"
Grid.Column="1" Margin="5,0,5,0"
ItemsSource="{Binding OdbcDataSources, Mode=TwoWay}"
Grid.Row="1" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Server}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
<ComboBox.ItemContainerStyle>
<Style TargetType="{x:Type ComboBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ComboBoxItem}">
<Border
x:Name="Bd"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<StackPanel Orientation="Vertical">
<Label Content="{Binding Server}" />
<Label Content="{Binding Driver}" />
</StackPanel>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsHighlighted" Value="True">
<Setter TargetName="Bd" Property="Background" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" />
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ComboBox.ItemContainerStyle>
</ComboBox>
I'm using MahApps Metro Styling in WPF and trying to add a style to the TreeViewItem so that the nodes have a folder icon next to them. (http://mahapps.com/MahApps.Metro/)
This is fairly straight forward, all I have to do is override the TreeViewItem header template and add in the image.
The problem is that for some reason the new template is not applied to the first entry in the tree as you can see blow:
All other tree nodes work fine but the first one refuses to have the style applied.
I have confirmed that this is something to do with the MahApps TreeView styling contained in Controls.TreeView.xaml (a new project without MahApps but with the same custom style works as expected) but I cannot see exactly what is going on.
Does anyone have any experience styling TreeViewItems when using MahApps?
<TreeView Grid.Column="0" Name="FolderView">
<TreeView.Resources>
<Style TargetType="{x:Type TreeViewItem}" BasedOn="{StaticResource MetroTreeViewItem}">
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Name="img"
Width="16"
Height="16"
Stretch="Fill"
Source="Images/Folder.png"
Margin="3"
VerticalAlignment="Center"
/>
<TextBlock Text="{Binding}" Margin="0,0" VerticalAlignment="Center" />
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</TreeView.Resources>
</TreeView>
try this`
<TreeView Grid.Column="0" Name="FolderView">
<TreeView.Resources>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TreeViewItem">
<Grid Background="Transparent">
<Grid.ColumnDefinitions>
<ColumnDefinition MinWidth="25" Width="Auto" />
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<ToggleButton x:Name="Expander" IsChecked="{Binding Path=IsExpanded,RelativeSource={RelativeSource TemplatedParent}}" ClickMode="Press">
<ToggleButton.Style>
<Style TargetType="ToggleButton">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Border Height="0" Width="0"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ToggleButton.Style>
</ToggleButton>
<ContentPresenter x:Name="PART_Header" ContentSource="Header"/>
<Grid x:Name="ItemsHost" Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2" Margin="0,-5,0,0">
<ItemsPresenter />
</Grid>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsExpanded" Value="false">
<Setter TargetName="ItemsHost" Property="Visibility" Value="Collapsed"/>
</Trigger>
<Trigger Property="HasItems" Value="false">
<Setter TargetName="Expander" Property="Visibility" Value="Hidden"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Name="img" Width="16" Height="16" Stretch="Fill" Source="Images/Folder.png" Margin="3" VerticalAlignment="Center"/>
<TextBlock Text="{Binding}" Margin="0,0" VerticalAlignment="Center" />
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</TreeView.Resources>
</TreeView>
I've found the solution :
You need to disable MahApps Metro style like this : Style="{x:Null}"
<TreeView Style="{x:Null}" Grid.Column="0" Grid.Row="1" >
<TreeView.Resources>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Width="20" Height="20" Stretch="Fill" Source="/Resources/folder.png" />
<TextBlock Text="{Binding}" />
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</TreeView.Resources>
</TreeView>
I am trying to make a style that only gets applied if the parent element of the element that the style refers to, has another specific style. Kind of like in CSS where you can do ".class1 .class2" to specify that the "class2" theme only applies if it is within an element with the class "class1".
I do not wish to use any form of external DLLs or libraries for this task. I want to know if it's possible to implement on my own.
I've tried using MultiTriggers with no luck.
I have a style that applies to all TextBlocks. I want the textblock to do the following:
If the font-size of the textblock is 11 and the parent element's style is "PinnedSuggestion", set the foreground color to "#FF505050".
If the font-size of the textblock is 11 and the parent element's style is "Suggestion", set the foreground color to "#FFCCCCCC".
The conditions that I have tried to write to make this work, are as follows (the font-size condition is true, but the other one is not). The conditions are inside a style that applies to all textblocks in general.
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=FontSize}" Value="11" />
<Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=Style}" Value="{StaticResource PinnedSuggestion}" />
</MultiDataTrigger.Conditions>
<Setter Property="Foreground" Value="#FFFF5050"></Setter>
</MultiDataTrigger>
I am not sure what I am doing wrong in this case. Below you see my ListBoxItem style for the "Suggestion" style. The PinnedSuggestion looks exactly the same (except for a few minor changes).
<Style x:Key="Suggestion" TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Grid Name="Container" Margin="0,0,0,0">
<Rectangle Margin="0,2,0,2" Stroke="Black" Name="Background" SnapsToDevicePixels="True" RadiusX="7" RadiusY="7" Width="Auto" Height="Auto" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"></Rectangle>
<Rectangle Margin="2,4,2,4" Name="BackgroundTwo" StrokeThickness="3" SnapsToDevicePixels="True" RadiusX="3" RadiusY="3" Width="Auto" Height="Auto" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"></Rectangle>
<ContentPresenter Margin="0"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The contentpresenter of that ListBoxItem style is what contains the textblocks that I want this technique to work with.
So, to summarize...
A ListBoxItem with the style "Suggestion" applied will have a TextBlock in it. The TextBlock style (due to its target type) will automatically apply to that, and I want the multitrigger conditions described above to work as they should.
My situation is kind of hard to explain. I explained everything as well as I could.
The parent element whose style you want to inspect is not the direct parent of the TextBlock; it could be arbitrarily higher in the visual tree. So your second condition needs to look for an ancestor of a particular type like this:
<Condition Binding="{Binding RelativeSource={RelativeSource AncestorType=ListBoxItem}, Path=Style}" Value="{StaticResource Suggestion}" />
Here is a complete working example, tested with .NET4:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Style x:Key="Suggestion" TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Grid Name="Container" Margin="0,0,0,0">
<Rectangle Margin="0,2,0,2" Stroke="Blue" Name="Background" SnapsToDevicePixels="True" RadiusX="7" RadiusY="7" Width="Auto" Height="Auto" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"></Rectangle>
<Rectangle Margin="2,4,2,4" Name="BackgroundTwo" StrokeThickness="3" SnapsToDevicePixels="True" RadiusX="3" RadiusY="3" Width="Auto" Height="Auto" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"></Rectangle>
<ContentPresenter Margin="0"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="PinnedSuggestion" TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Grid Name="Container" Margin="0,0,0,0">
<Rectangle Margin="0,2,0,2" Stroke="Green" Name="Background" SnapsToDevicePixels="True" RadiusX="7" RadiusY="7" Width="Auto" Height="Auto" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"></Rectangle>
<Rectangle Margin="2,4,2,4" Name="BackgroundTwo" StrokeThickness="3" SnapsToDevicePixels="True" RadiusX="3" RadiusY="3" Width="Auto" Height="Auto" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"></Rectangle>
<ContentPresenter Margin="0"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="Neutral" TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Grid Name="Container" Margin="0,0,0,0">
<Rectangle Margin="0,2,0,2" Stroke="Black" Name="Background" SnapsToDevicePixels="True" RadiusX="7" RadiusY="7" Width="Auto" Height="Auto" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"></Rectangle>
<Rectangle Margin="2,4,2,4" Name="BackgroundTwo" StrokeThickness="3" SnapsToDevicePixels="True" RadiusX="3" RadiusY="3" Width="Auto" Height="Auto" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"></Rectangle>
<ContentPresenter Margin="0"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=FontSize}" Value="11" />
<Condition Binding="{Binding RelativeSource={RelativeSource AncestorType=ListBoxItem}, Path=Style}" Value="{StaticResource Suggestion}" />
</MultiDataTrigger.Conditions>
<Setter Property="Foreground" Value="Red"></Setter>
</MultiDataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=FontSize}" Value="11" />
<Condition Binding="{Binding RelativeSource={RelativeSource AncestorType=ListBoxItem}, Path=Style}" Value="{StaticResource PinnedSuggestion}" />
</MultiDataTrigger.Conditions>
<Setter Property="Foreground" Value="Yellow"></Setter>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<ListBox>
<ListBoxItem Style="{StaticResource Neutral}">
<TextBlock FontSize="10" Text="Style=Neutral, FontSize=10"/>
</ListBoxItem>
<ListBoxItem Style="{StaticResource Neutral}">
<TextBlock FontSize="11" Text="Style=Neutral, FontSize=11"/>
</ListBoxItem>
<ListBoxItem Style="{StaticResource Suggestion}">
<TextBlock FontSize="10" Text="Style=Suggestion, FontSize=10"/>
</ListBoxItem>
<ListBoxItem Style="{StaticResource Suggestion}">
<TextBlock FontSize="11" Text="Style=Suggestion, FontSize=11"/>
</ListBoxItem>
<ListBoxItem Style="{StaticResource PinnedSuggestion}">
<TextBlock FontSize="10" Text="Style=PinnedSuggestion, FontSize=10"/>
</ListBoxItem>
<ListBoxItem Style="{StaticResource PinnedSuggestion}">
<TextBlock FontSize="11" Text="Style=PinnedSuggestion, FontSize=11"/>
</ListBoxItem>
</ListBox>
</Grid>