I want to create a custom WPF dropdown menu, so I created a User control which contains a ToggleButton and a Popup control. The popup appears when I click on the button.
Now I want to add a mouse hover effect on the menu items in the popup: but the LinearGradientBrush is not working with alpha channels:
<UserControl.Resources>
...
<Style x:Key="SubMenuItemStyle" TargetType="{x:Type MenuItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="MenuItem">
<Grid Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" ClipToBounds="True">
<Rectangle x:Name="rectangle" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
Stroke="{TemplateBinding BorderBrush}" StrokeThickness="{TemplateBinding BorderThickness}"
Fill="{TemplateBinding Background}" />
<StackPanel>
<TextBlock x:Name="text" Text="{TemplateBinding Header}" Foreground="{TemplateBinding Foreground}" />
</StackPanel>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Stroke" TargetName="rectangle" Value="#30000000"/>
<Setter Property="Fill" TargetName="rectangle">
<Setter.Value>
<LinearGradientBrush EndPoint="0,0" StartPoint="1,1">
<GradientStop Color="#10000000" Offset="0"/>
<GradientStop Color="#10FFFFFF" Offset="1"/>
<!-- Not works... -->
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" TargetName="text" Value="#FF9A9A9A"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Grid>
<Controls:ToggleImageButton Style="{DynamicResource ArrowMenuStyle}" x:Name="imageButton" Height="21" />
<Popup x:Name="popup" PlacementTarget="{Binding ElementName=imageButton}" Placement="Bottom" StaysOpen="False" IsOpen="{Binding ElementName=imageButton, Path=IsChecked}">
<ItemsControl ItemsSource="{Binding MenuCommands}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<MenuItem Header="{Binding Name}" Command="{Binding Command}" Background="{Binding ElementName=popupMenuControl, Path=MenuBackground}" Foreground="{Binding ElementName=popupMenuControl, Path=MenuForeground}" Click="MenuItem_Click" Style="{StaticResource SubMenuItemStyle}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Popup>
</Grid>
When I set the GradientBrush to this, everything works fine:
<LinearGradientBrush EndPoint="0,0" StartPoint="1,1">
<GradientStop Color="Green" Offset="0"/>
<GradientStop Color="Yellow" Offset="1"/>
</LinearGradientBrush>
But it seems the Alpha channel breaks the whole thing, and what I see is a black rectangle.
...Any idea?
If I put the MenuItems inside a Menu container, the Menu overrides my styles...
Thanks in advance!
have you set AllowsTransparency to true?
Related
I'm made a style for DataGridColumnHeader. Most of it is working, but I get second Border through my header text and I don't know how to solve this. See the image below for the result I get:
I only want the one border that's below the text. This is the style I've made:
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridColumnHeader}">
<Grid Name="HeaderGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="14" />
</Grid.ColumnDefinitions>
<Border
x:Name="BackgroundBorder"
Grid.ColumnSpan="2"
BorderBrush="{DynamicResource Dark}"
BorderThickness="0,0,1,1"/>
<ContentPresenter
Grid.Column="0"
Margin="6,3,6,3"
VerticalAlignment="Center" />
<Path
x:Name="SortArrow"
Grid.Column="1"
Width="6"
Height="4"
Margin="0,0,8,0"
VerticalAlignment="Center"
Data="M 0 4 L 3.5 0 L 7 4 Z"
Fill="{DynamicResource Dark}"
RenderTransformOrigin="0.5,0.4"
Stretch="Fill"
Visibility="Collapsed" />
<Thumb
x:Name="PART_RightHeaderGripper"
Grid.Column="1"
HorizontalAlignment="Right"
Cursor="SizeWE">
<Thumb.Style>
<Style TargetType="{x:Type Thumb}">
<Setter Property="Width" Value="2" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Thumb}">
<Border Background="Transparent" BorderBrush="Transparent" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Thumb.Style>
</Thumb>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="SortDirection" Value="Ascending">
<Setter TargetName="SortArrow" Property="Visibility" Value="Visible" />
<Setter TargetName="SortArrow" Property="RenderTransform">
<Setter.Value>
<RotateTransform Angle="180" />
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="SortDirection" Value="Descending">
<Setter TargetName="SortArrow" Property="Visibility" Value="Visible" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Can someone show me where I went wrong with the style I made?
EDIT:
I've put all the elements inside the border, but this doesn't seem to fix it.
When I give the border a different thickness, this is the result:
BorderThickness="0,2,1,4"
Both the top and bottom border appear twice.
Giving the header a MinHeight removes the double borders. This doesn't seem like a perfect fix, but works for now.
I recommend you take a careful look at how the original template works.
It's not clear what you're trying to achieve, but you need two thumbs for resizing.
On the following page
https://learn.microsoft.com/en-us/dotnet/framework/wpf/controls/datagrid-styles-and-templates
Search on columnheader then cycle through the hits until you see markup looks like:
<!--Style and template for the DataGridColumnHeader.-->
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="VerticalContentAlignment"
Value="Center" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridColumnHeader}">
<Grid>
<Border x:Name="columnHeaderBorder"
BorderThickness="1"
Padding="3,0,3,0">
<Border.BorderBrush>
<LinearGradientBrush EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="{DynamicResource BorderLightColor}"
Offset="0" />
<GradientStop Color="{DynamicResource BorderDarkColor}"
Offset="1" />
</LinearGradientBrush>
</Border.BorderBrush>
<Border.Background>
<LinearGradientBrush EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="0" />
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="1" />
</LinearGradientBrush>
</Border.Background>
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</Border>
<Thumb x:Name="PART_LeftHeaderGripper"
HorizontalAlignment="Left"
Style="{StaticResource ColumnHeaderGripperStyle}" />
<Thumb x:Name="PART_RightHeaderGripper"
HorizontalAlignment="Right"
Style="{StaticResource ColumnHeaderGripperStyle}" />
</Grid>
</ControlTemplate>
</Setter.Value>
Notice particularly:
You need a PART_LeftHeaderGripper thumb.
Both thumbs are arranged using horizontalalignment left and right which would stop them filling the cell like yours does.
There is a width set in the style.
As a final piece of advice.
I strongly recommend you start with a working copy of a standard control template. Then carefully make small iterative changes. That way, when it breaks you know what broke it.
I'm trying to give a style to items in a ListBox, I made this style previously for ListViewItem which about TextBlock, Image and a Border which changes its color when an item event raised (IsSelected, IsMouseOver, IsSelectionActive), Now I want to keep this style and apply it to any item added to a ListBox
<Style x:Key="ListBoxPCInfoStyle" TargetType="{x:Type ListBoxItem}">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
<Setter Property="VerticalContentAlignment" Value="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
<Setter Property="Padding" Value="2,0,0,0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Grid HorizontalAlignment="Left" Height="74" VerticalAlignment="Top" Width="68">
<Image x:Name="Img" Width="56" Height="56" Margin="6,0,6,18" Source="{Binding RelativeSource={RelativeSource TemplatedParent}, Path= ActualHeight}"/>
<Border x:Name="border" BorderBrush="{x:Null}" BorderThickness="1" HorizontalAlignment="Left" Height="74" VerticalAlignment="Top" Width="68" CornerRadius="2.5"/>
<TextBlock HorizontalAlignment="Stretch" TextWrapping="Wrap" Text="{TemplateBinding Name}" VerticalAlignment="Bottom" Width="Auto" Height="17" TextAlignment="Center" Margin="4,0"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" TargetName="border">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#33C1DEFF" Offset="0"/>
<GradientStop Color="#41A5CDFF" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="BorderBrush" TargetName="border" Value="#FF7DA2CE"/>
</Trigger>
<Trigger Property="IsSelected" Value="true">
<Setter Property="BorderBrush" TargetName="border" Value="#FF7DA2CE"/>
<Setter Property="Background" TargetName="border">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#97C1DEFF" Offset="0"/>
<GradientStop Color="#A7A5CDFF" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="true"/>
<Condition Property="Selector.IsSelectionActive" Value="false"/>
</MultiTrigger.Conditions>
<Setter Property="BorderBrush" TargetName="border" Value="#FFB4B4B4"/>
<Setter Property="Background" TargetName="border">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#7FE5E5E5" Offset="0"/>
<GradientStop Color="#B2CCCCCC" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</MultiTrigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And I have this ListBox
<ListBox x:Name="ListHosts" Background="{x:Null}" BorderBrush="{x:Null}">
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Border x:Name="border" BorderBrush="{x:Null}" BorderThickness="1" HorizontalAlignment="Left" Height="20" VerticalAlignment="Top" Width="50" CornerRadius="2.5"/>
<Image x:Name="Img" Source="BtnImg/Computer.png" Stretch="None" Margin="3,0,10,0"/>
<TextBlock x:Name="PCName" Margin="0,7" TextWrapping="Wrap" Height="16" HorizontalAlignment="Left"><Run Text="{Binding Name}"/></TextBlock>
</StackPanel>
</DataTemplate>
</ListBox>
I feel like I'm missing something simple here... can someone help me spot it?
2 Options:
Either remove the x:Key from the style:
<Style TargetType="{x:Type ListBoxItem}">
<!-- ... -->
this will make the style apply to all ListBoxItems in the resource scope.
or
Explicitly reference the style in your ListBox:
<ListBox ItemContainerStyle="{StaticResource ListBoxPCInfoStyle}">
<!-- ... -->
-------------------------------------------------------------------------------------------
Anyways, all your XAML is wrong. You're defining the ListBoxItem.Template like this:
<Grid HorizontalAlignment="Left" Height="74" VerticalAlignment="Top" Width="68">
<Image x:Name="Img" Width="56" Height="56" Margin="6,0,6,18" Source="{Binding RelativeSource={RelativeSource TemplatedParent}, Path= ActualHeight}"/>
<Border x:Name="border" BorderBrush="{x:Null}" BorderThickness="1" HorizontalAlignment="Left" Height="74" VerticalAlignment="Top" Width="68" CornerRadius="2.5"/>
<TextBlock HorizontalAlignment="Stretch" TextWrapping="Wrap" Text="{TemplateBinding Name}" VerticalAlignment="Bottom" Width="Auto" Height="17" TextAlignment="Center" Margin="4,0"/>
</Grid>
Which leaves no chance for custom DataTemplates to be introduced anywhere. You need to leave a ContentPresenter somewhere, so that WPF has a chance to put DataTemplated content inside that.
And the TextBlock makes no sense. You're binding against the ListBoxItem.Name property, which is completely irrelevant and makes no sense to be shown in the UI, and which you have no control over, anyways.
Data does not belong into ControlTemplates, only DataTemplates.
Change your template like so:
<Grid HorizontalAlignment="Left" Height="74" VerticalAlignment="Top" Width="68">
<Image x:Name="Img" Width="56" Height="56" Margin="6,0,6,18" Source="{Binding RelativeSource={RelativeSource TemplatedParent}, Path= ActualHeight}"/>
<Border x:Name="border" BorderBrush="{x:Null}" BorderThickness="1" HorizontalAlignment="Left" Height="74" VerticalAlignment="Top" Width="68" CornerRadius="2.5"/>
<ContentPresenter ContentSource="Content"/>
</Grid>
And the ListBox XAML is also wrong:
By doing this:
<ListBox ...>
<DataTemplate>
<!-- ... -->
</DataTemplate>
</ListBox>
You're putting the DataTemplate as an item inside the ListBox, which is not what you want.
You need to specifically assign the DataTemplate as the ItemTemplate for the ListBox:
<ListBox ...>
<ListBox.ItemTemplate>
<DataTemplate>
<!-- ... -->
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
And why is the Image.Source bound to a property of type double? That makes no sense.
Either put a specific resource there:
<Image Source="/resources/somepic.png"/>
or
if you want to dynamically change the image dependending on certain data, then that belongs into the DataTemplate, not the ControlTemplate.
-------------------------------------------------------------------------------------------
I suggest you read up the following material:
MSDN: WPF Content Model
MSDN: WPF Controls Content Model
Dr. WPF: ItemsControls A to Z
I would like to mimic a style for a group of ToggleButtons as in the below image. Only one of the buttons can be "Checked" at any time.
My question is related to styling:
I'd like to have rounded corners on the leftmost button and the rightmost button as in the image but if there is a button between (like in the image), that should not have rounded corners. Sometimes there might only be two buttons to toggle.
I need style for different states: "Normal/Unchecked", "Mouseover", "Pressed" and "Checked" at the minimum.
The current control I am using for this is done like this:
<StackPanel Orientation="Horizontal" >
<RadioButton Style="{StaticResource {x:Type ToggleButton}}" Content="All" Padding="12,8,12,8" GroupName="View" />
<RadioButton Style="{StaticResource {x:Type ToggleButton}}" Content="Geolocated" Padding="12,8,12,8" GroupName="View" />
<RadioButton Style="{StaticResource {x:Type ToggleButton}}" Content="Non Geolocated" Padding="12,8,12,8" GroupName="View" />
</StackPanel>
In the StackPanel Resources I am trying to set Style for ToggleButton but I'm pretty lost how to achieve the result as in the image above.
This may not be the easiest/best approach, but I took a stab at knocking up some ControlTemplates using Kaxaml, to produce something that looks like this:
You could store these templates in a ResourceDictionary and apply them when required, or use them if you were building your button list on the fly.
I actually created three slightly different styles, one for the left and right buttons, and one for the middle (you may be able to simplify this with extending/inheriting styles). Some repeated code omitted.
<Grid>
<Grid.Resources>
<!-- Brushes for colours/backgrounds -->
<SolidColorBrush x:Key="FontBrush" Color="#DDDDDD"/>
<LinearGradientBrush x:Key="BgBrush1" StartPoint="0,0" EndPoint="0,1">
<GradientStop Offset="0" Color="#888888"/>
<GradientStop Offset="1" Color="#222222"/>
</LinearGradientBrush>
<SolidColorBrush x:Key="BorderBrush1" Color="#333333"/>
<LinearGradientBrush x:Key="CheckedBrush" StartPoint="0,0" EndPoint="0,1">
<GradientStop Offset="0" Color="#555555"/>
<GradientStop Offset="1" Color="#111111"/>
</LinearGradientBrush>
<!-- Left Button Template -->
<ControlTemplate x:Key="ToggleButtonLeft" TargetType="{x:Type ToggleButton}">
<Border
Name="Border"
Background="{StaticResource BgBrush1}"
BorderBrush="{StaticResource BorderBrush1}"
BorderThickness="1"
CornerRadius="5,0,0,5">
<ContentPresenter
HorizontalAlignment="Center"
Margin="{TemplateBinding Padding}"
VerticalAlignment="Center"
Content="{TemplateBinding Content}"
TextBlock.FontWeight="Bold"
TextBlock.Foreground="{StaticResource FontBrush}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="ToggleButton.IsMouseOver" Value="true">
<Setter TargetName="Border" Property="Background" Value="#808080"/>
</Trigger>
<Trigger Property="IsChecked" Value="true">
<Setter TargetName="Border" Property="Background" Value="{StaticResource CheckedBrush}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<!-- Middle Button(s) Template -->
<ControlTemplate x:Key="ToggleButtonMid" TargetType="{x:Type ToggleButton}">
<Border
Name="Border"
Background="{StaticResource BgBrush1}"
BorderBrush="{StaticResource BorderBrush1}"
BorderThickness="0,1,0,1"
CornerRadius="0" />
<!-- Other code identical to Left Button Template -->
</ControlTemplate>
<!-- Right Button Template -->
<ControlTemplate x:Key="ToggleButtonRight" TargetType="{x:Type ToggleButton}">
<Border
Name="Border"
Background="{StaticResource BgBrush1}"
BorderBrush="{StaticResource BorderBrush1}"
BorderThickness="1"
CornerRadius="0, 5, 5, 0" />
<!-- Other code identical to Left Button Template -->
</ControlTemplate>
</Grid.Resources>
<!-- Example Usage -->
<Grid Background="#555555">
<StackPanel Height="25" Orientation="Horizontal" Margin="5">
<RadioButton Content="All" GroupName="View" Padding="2" Template="{DynamicResource ToggleButtonLeft}"/>
<RadioButton Content="Geolocated" GroupName="View" Padding="2" Template="{DynamicResource ToggleButtonMid}"/>
<RadioButton Content="Non Geolocated" GroupName="View" Padding="2" Template="{DynamicResource ToggleButtonRight}"/>
</StackPanel>
</Grid>
</Grid>
You would have to add additional Triggers etc. for the IsPressed state, and any others required (e.g IsEnabled).
I am using custom ComboBox with style, I want to set width of a Popup dynamically via coading so that to auto adjust the width of popup
so I wanted to change Popup like second image dynamically(whatever may be thesize of ComboBox)
I am using style as follows
<Style x:Key="ComboBoxStyle" TargetType="{x:Type ComboBox}">
<Setter Property="Foreground" Value="#666666"/>
<Setter Property="FontFamily" Value="Arial"/>
<Setter Property="FontSize" Value="13"/>
<Setter Property="Height" Value="28"/>
<Setter Property="BorderThickness" Value="1.5"/>
<Setter Property="Padding" Value="4,3"/>
<Setter Property="Margin" Value="5"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ComboBox}">
<Grid>
<Popup Margin="1" x:Name="PART_Popup" AllowsTransparency="true" IsOpen="{Binding Path=IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}}" Placement="Bottom" PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}" Grid.ColumnSpan="2" Width="{Binding ActualWidth,RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Grid}}">
<Border Name="DropDownBorder" Width="Auto" Height="Auto" BorderThickness="1,0,1,1" CornerRadius="0,0,4,4" BorderBrush="#FFbbbbbb">
<Border.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="White" Offset="0" />
<GradientStop Color="#FFE9E9E9" Offset="1" />
</LinearGradientBrush>
</Border.Background>
<ScrollViewer CanContentScroll="true">
<ItemsPresenter />
</ScrollViewer>
</Border>
</Popup>
<ToggleButton Style="{StaticResource cmbToggle}" Grid.ColumnSpan="2" IsChecked="{Binding Path=IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"/>
<ContentPresenter HorizontalAlignment="Left" Margin="5,0,0,0" VerticalAlignment="Center" IsHitTestVisible="false" Content="{TemplateBinding SelectionBoxItem}" ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="cmbToggle" TargetType="{x:Type ToggleButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Border Name="cmbBorder" CornerRadius="3" BorderBrush="#FFaaaaaa" BorderThickness="1.5">
<Border.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="White" Offset="0" />
<GradientStop Color="#FFE9E9E9" Offset="1" />
</LinearGradientBrush>
</Border.Background>
<Border BorderBrush="#FFaaaaaa" BorderThickness="1,0,0,0" Width="20" HorizontalAlignment="Right">
<Polygon Name="pol" Fill="#FF787878" Points="4,9 8,14 12,9" Stroke="#FF787878" StrokeThickness="0" Margin="1 1 0 0">
</Polygon>
</Border>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="CornerRadius" TargetName="cmbBorder" Value="4,4,0,0"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
So My idea is to change width of Popup dynamically(Combobox width - togglebutton width = popup width).I have written style in App.xaml
How to do this, Please help me. Thanks in advance.
Ok so in your ToggleButton Style we can see the Border holding Polygon arrow is 20 in Width. That's the Width to be removed from the Popup
Thus we can do something like:
Firstly add 2 Column's to the Grid in ComboBox ControlTemplate
<ControlTemplate TargetType="{x:Type ComboBox}">
<Grid>
<!-- New Bit -->
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
<!-- End of New Bit -->
<Popup x:Name="PART_Popup"
Grid.ColumnSpan="2"
...
and then update the Width of Popup to
<Popup x:Name="PART_Popup"
Grid.ColumnSpan="2"
Width="{Binding Path=ColumnDefinitions[0].ActualWidth,
RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType=Grid}}"
...
Your Style already has ColumnSpan mentioned on appropriate controls, so nothing else is needed. This should give you the output your looking for.
you can directly use
<ComboBox.Resources>
<Style TargetType="{x:Type Popup}">
<Setter Property="Width" Value="110"/>
</Style>
</ComboBox.Resources>
Using Dhaval Patel's solution bound to a view model property did the trick.
I calculate the max width using FormattedText when the collection changes and it bind it below.
<ComboBox.Resources>
<Style TargetType="{x:Type Popup}">
<Setter Property="Width" Value="{Binding MaxWidthOfMyCollection"/>
</Style>
</ComboBox.Resources>
I have the following defined in my control:
<Style TargetType="primitives:CalendarDayButton" x:Key="EventCalendarDayButton">
<Setter Property="Background" Value="#FFBADDE9"/>
<Setter Property="MinWidth" Value="5"/>
<Setter Property="MinHeight" Value="5"/>
<Setter Property="FontSize">
<Setter.Value>
<Binding Path="DayFontSize">
<Binding.RelativeSource>
<RelativeSource Mode="FindAncestor" AncestorType="{x:Type toolkit:Calendar}" />
</Binding.RelativeSource>
</Binding>
</Setter.Value>
</Setter>
<Setter Property="HorizontalContentAlignment" Value="Right"/>
<Setter Property="VerticalContentAlignment" Value="Top"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="primitives:CalendarDayButton">
<Grid MouseDown="Grid_MouseDown">
<Grid.RowDefinitions>
<RowDefinition Height="18" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Rectangle x:Name="SelectedBackground" Grid.Row="1" RadiusX="1" RadiusY="1" Opacity="0" Fill="{TemplateBinding Background}"/>
<Rectangle x:Name="Background" Grid.Row="1" RadiusX="1" RadiusY="1" Opacity="0" Fill="{TemplateBinding Background}" />
<Rectangle x:Name="InactiveBackground" Grid.Row="1" RadiusX="1" RadiusY="1" Opacity="0" Fill="#FFA5BFE1"/>
<Border>
<Border.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop x:Name="StartGradient" Color="#FFD5E2F2" Offset="0"/>
<GradientStop x:Name="EndGradient" Color="#FFB9C9DD" Offset="1"/>
</LinearGradientBrush>
</Border.Background>
<ContentPresenter x:Name="NormalText" Margin="5,1,5,1" VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
<TextElement.Foreground>
<SolidColorBrush x:Name="selectedText" Color="#FF333333" />
</TextElement.Foreground>
</ContentPresenter>
</Border>
<Rectangle x:Name="Border" StrokeThickness="0.5" Grid.RowSpan="2" SnapsToDevicePixels="True">
<Rectangle.Stroke>
<SolidColorBrush x:Name="BorderBrush" Color="#FF5D8CC9"/>
</Rectangle.Stroke>
</Rectangle>
<Path x:Name="Blackout" Grid.Row="1" Opacity="0" Margin="3" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" RenderTransformOrigin="0.5,0.5" Fill="#FF000000" Stretch="Fill" Data="M8.1772461,11.029181 L10.433105,11.029181 L11.700684,12.801641 L12.973633,11.029181 L15.191895,11.029181 L12.844727,13.999395 L15.21875,17.060919 L12.962891,17.060919 L11.673828,15.256231 L10.352539,17.060919 L8.1396484,17.060919 L10.519043,14.042364 z"/>
<Rectangle Width="0" x:Name="DayButtonFocusVisual" Grid.Row="1" Visibility="Collapsed" IsHitTestVisible="false" RadiusX="1" RadiusY="1" Stroke="#FF45D6FA"/>
<Button x:Name="ActivateDayViewOnDay" Grid.Row="0" Opacity="0.3" Height="15" Margin="1,1,1,1" PreviewMouseLeftButtonDown="DayView_Click" />
<ScrollViewer Grid.Row="1" >
<ScrollViewer.Content>
<local:TestListBox
x:Name="eventsLbx"
Background="Transparent"
BorderBrush="Transparent"
>
<local:TestListBox.ItemsSource>
<MultiBinding Converter="{StaticResource calendarEventsConverter}">
<Binding RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type local:EventCalendar}}" Path="CalendarEvents"/>
<Binding RelativeSource="{RelativeSource Mode=Self}" Path="DataContext"/>
</MultiBinding>
</local:TestListBox.ItemsSource>
<local:TestListBox.ItemTemplate>
<DataTemplate>
<TextBlock TextTrimming="CharacterEllipsis" HorizontalAlignment="Center" FontSize="12" Text="{Binding Text}" />
</DataTemplate>
</local:TestListBox.ItemTemplate>
</local:TestListBox>
</ScrollViewer.Content>
</ScrollViewer>
</Grid>
<ControlTemplate.Triggers>
<Trigger SourceName="eventsLbx" Property="HasItems" Value="False">
<Setter TargetName="eventsLbx" Property="Visibility" Value="Hidden"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Now if there are more items than are visible, then the scrollviewer appears properly but the user CANNOT drag the scrollviewer middle button for scrolling.
The user can click on the arrows at the end of the scrollviewer to scroll but he cannot click the bar that appears on the scrollbar and drag it to actually scroll the contents.
I cannot figure out why this is happening...
If you want to scroll the items in your ListBox, you do not need to wrap it in a ScrollViewer. The ListBox natively supports scrolling. That means, if your ListBox is too small to display all its items, it automatically adds ScrollBars to the side.
Your ScrollViewer and ListBox are inside a Grid, and you have some code behind the MouseDown event of that Grid.
<Grid MouseDown="Grid_MouseDown">
Something you're doing in that method may be getting in the way of the mouse mechanisms of the ScrollViewer, disrupting event bubbling or something like that.
Check your code-behind, or post it here so we can help you with it :)