Adding image on top of ListBoxItem in WPF - wpf

I have a ListBox with some ListBoxItems. Each ListBoxItem contains some text and a background image. When the user clicks a ListBoxItem I want to add an image on top of the ListBoxItem (it decorates the item with some additional looks).
I'm looking for a way to overlay the image onto the clicked ListBoxItem. That's the code I have so far:
<ListBox Margin="0,34,0,25.113" Background="{x:Null}" BorderThickness="0">
<ListBoxItem Content="First Item" Height="71.96" Margin="0,10,0,0">
<ListBoxItem.Background>
<ImageBrush ImageSource="Untitled-4.png"/>
</ListBoxItem.Background>
</ListBoxItem>
</ListBox>

Put your ListBoxItem.Content in a panel which allows overlapping controls, such as a Grid, and make your top image's Visibililty be based on ListBoxItem.IsSelected
<ListBox.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
</ListBox.Resources>
<ListBoxItem Height="71.96" Margin="0,10,0,0">
<ListBoxItem.Background>
<ImageBrush ImageSource="Untitled-4.png"/>
</ListBoxItem.Background>
<Grid>
<TextBlock Text="First Item"
VerticalAlignment="Center" HorizontalAlignment="Center" />
<Image Source="SomeImage.jpg"
Visibility="{Binding IsSelected,
RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}},
Converter={StaticResource BooleanToVisibilityConverter}}" />
</Grid>
</ListBoxItem>
Edit
You can also remove the blue background for the SelectedItem by overwritting the HighlightBrush Color and making it Transparent
<ListBox.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
<Style TargetType="{x:Type ListBoxItem}">
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent" />
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Transparent" />
</Style.Resources>
</Style>
</ListBox.Resources>

Related

How can I edit the Menu Item icon when I add the item via Item Source?

I have an MenuItem and in this MenuItem I add an ItemSource, so that the Items of this menuItem are createt from an Observable Collection. My MenuItem look like that:
<MenuItem Foreground="Black"
FontFamily="{Binding ElementName=wpfAudit, Path=FontFamily}"
FontSize="{Binding ElementName=wpfAudit, Path=FontSize}"
FontWeight="{Binding ElementName=wpfAudit, Path=FontWeight}"
Header="Artikellabel Drucker"
ItemsSource="{Binding ocArtikellabeldrucker, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}">
</MenuItem>
Now I want to edit the MenuItem.Icon of the Items which I created with an ItemSource.
What I tried is this:
<MenuItem.Resources>
<RadioButton x:Key="RadioButtonResource" x:Shared="false" HorizontalAlignment="Center"
GroupName="MenuItemRadio" IsHitTestVisible="False" IsChecked="{Binding IstDrucker}" Style="{StaticResource {x:Type RadioButton}}"/>
</MenuItem.Resources>
But this dosent work. So how can I get that to work? Maybe with an ControlTemplate ?
Something like below will work
<Style x:Key="MenuItemStyle" TargetType="{x:Type MenuItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type MenuItem}">
<StackPanel Orientation="Horizontal">
<RadioButton IsChecked="True" Content="Test Item" />
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

XAML ViewBox forces a bad rescale on ListBoxItem MouseOver

I have the following XAML layout (ListBox where the Items are RadioButtons styled as ToggleButtons). The ListBox and the ToggleButton items scales and fills the ToggleButton items nicely to adapt to the window size. This is just as I want, but when I have the mouse over a ToggleButton in the ListBox, the style sets the Text to be bold. This is also what I want, but the problem is that it makes the button slightly bigger. When having the mouse over the ToggleButton item with the longest text the ViewBox refreshes and rescales all the ToggleButton controls. It looks like all the ToggleButtons makes a jump. How can I prevent such rescaling of the ToggleButtons still filling out the complete Grid Column and Row with the ListBox and its ToggleButton items?
<Viewbox Stretch="UniformToFill" Grid.Row="1" Grid.Column="0" VerticalAlignment="Stretch" Margin="5,0,0,15">
<Grid x:Name="LeftSide" Grid.Row="1" Grid.Column="0" VerticalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<ListBox Grid.Column="0" Grid.Row="0" Grid.RowSpan="10" ItemsSource="{Binding LeftPaneViewModelInfoItems, UpdateSourceTrigger=PropertyChanged}" Background="Transparent" SelectedItem="{Binding SelectedViewModelInfoItem}">
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Background" Value="Transparent" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<ContentPresenter />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<RadioButton
Content="{Binding Text}"
GroupName="DisplayPage"
IsChecked="{Binding IsSelected, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}}}"
Style="{StaticResource RadioButtonToggleButtonStyle}"
>
</RadioButton>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Viewbox>
Did not find a good solution. I ended up removing the bold setter property from the Mouse Over style.

How to select only a line shape instead of selecting a big square

I'm working on a WPF project that has a ListBox bound to a collection. This ListBox shows the elements in a canvas since these elements are ellipses and lines.
I am developing an application where I can draw entities (ellipses) and connectors (lines). That's already working.
I also want to be able to select either a ellipse or a line which I can already do it, since this capability is provided by the ListBox. However, when I select a line, the selected line looks like an ugly big blue square!
Is there a way to select only the pure line?
Here is how my current ListBox implementation looks like:
<ListBox ItemsSource="{Binding Elements}" >
<ItemsControl.ItemContainerStyle>
<Style>
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}"
Color="Transparent"/>
</Style.Resources>
<Setter Property="Canvas.Left" Value="{Binding CanvasLeft}" />
<Setter Property="Canvas.Top" Value="{Binding CanvasTop}" />
<Setter Property="Panel.ZIndex" Value="{Binding ZIndex, Mode=TwoWay}" />
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.Resources>
<DataTemplate DataType="{x:Type vm:EntityViewModel}" >
<Viewbox>
<Grid>
<Ellipse myb:DraggableBehavior.IsDraggingEnabled="True"
Stroke="Black"
Width="{Binding ShapeWidth, Mode=TwoWay}"
Height="{Binding ShapeHeight, Mode=TwoWay}"
Canvas.Left="{Binding X1, Mode=TwoWay}"
Canvas.Top="{Binding Y1, Mode=TwoWay}"
Fill="{Binding Background}"
Panel.ZIndex="{Binding ZIndex, Mode=TwoWay}" >
</Ellipse>
<TextBlock Text="{Binding StatePropertiesViewModel.Name}"
HorizontalAlignment="Center"
TextAlignment="Center"
VerticalAlignment="Center" />
</Grid>
</Viewbox>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:LineViewModel}" >
<Line X1="{Binding X1, Mode=TwoWay}"
Y1="{Binding Y1, Mode=TwoWay}"
X2="{Binding X2, Mode=TwoWay}"
Y2="{Binding Y2, Mode=TwoWay}"
Stroke="{Binding Color, Mode=TwoWay}"
StrokeThickness="{Binding Thickness, Mode=TwoWay}"
Panel.ZIndex="{Binding ZIndex, Mode=TwoWay}"
/>
</DataTemplate>
</ItemsControl.Resources>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ListBox>
Update
After following #AbhinavSharma's advice:
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}"
Color="Transparent"/>
</Style.Resources>
It seemed that the blue square selection area is not visible now, it looks better. However, it is still there because, for example, if I have a Line shape over an Ellipse, I cannot select the ellipse since the invisible selected Line area is still there. i.e. what I get selected when clicking on it is the line, not the ellipse. So, is there a way to reduce the selection area just to the area of the shape itself?
Thanks in advance.

Binding 1000usercontrols to listbox is slow wpf

I am having a listbox to which i am binding around 1000usercontrols with itemspaneltemplate as grid and i am placing each usercontrol by specifying rows and columns which is working fine.
But problem is it takes too much of time to load i even used backgroundworker process also but also no use.
Please help me what is the solution for the above problem.
<ListBox VerticalAlignment="Top" ItemsSource="{Binding Session.LstPlannedLightChkEntity,ElementName=uc, IsAsync=True}" Grid.Row="0"
VirtualizingStackPanel.IsVirtualizing="True" VirtualizingStackPanel.VirtualizationMode="Recycling"
local:DragDropHelper.IsDragSource="true" local:DragDropHelper.IsDropTarget="true"
local:DragDropHelper.DragDropTemplate="{StaticResource planetTemplateDrag}"
ScrollViewer.VerticalScrollBarVisibility="Hidden" ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.CanContentScroll="True"
>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Grid.Row" Value="{Binding Row}"/>
<Setter Property="Grid.Column" Value="{Binding Column}"/>
<Setter Property="Grid.ColumnSpan" Value="{Binding ColumnSpan}" />
<Style.Resources>
<!-- Background of selected item when focussed -->
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent"/>
<!-- Background of selected item when not focussed -->
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Transparent" />
</Style.Resources>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<local:GridControl x:Name="gcMenuPlanned" VerticalAlignment="Stretch" Margin="-1,-1,0,0"
ShowCustomGridLines="True" GridLineBrush="#FFE4E7EB" GridLineThickness="0.5" SnapsToDevicePixels="True">
<local:GridControl.ContextMenu>
<ContextMenu >
<MenuItem Foreground="Black" Header="Add Task" Click="AddTask_Click" Tag="{Binding CheckType}" />
<MenuItem Foreground="Black" Header="Goto..." Click="miGoto_Click" Tag="{Binding CheckType}" />
</ContextMenu>
</local:GridControl.ContextMenu>
</local:GridControl>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<local:LightFCCheckBlockControl CheckColor="#FFA2CAEB" MouseLeftButtonDown="LightFCCheckBlockControl_MouseLeftButtonDown">
<local:LightFCCheckBlockControl.ContextMenu>
<ContextMenu >
<MenuItem Foreground="Black" Header="Edit" Click="miEdit_Click" Tag="{Binding CheckType}" Visibility="{Binding Path=OpacityForCCheck,Converter={StaticResource opacityToVisibility}}"/>
<MenuItem Foreground="Black" Style="{StaticResource MenuItemBindingStyle }" Click="miFreeze_Click" Tag="{Binding CheckType}" Visibility="{Binding Path=OpacityForCCheck,Converter={StaticResource opacityToVisibility}}">
</MenuItem>
<MenuItem Foreground="Black" Click="RemoveChecks_Click" Header="Remove Checks" Tag="{Binding CheckType}"/>
<MenuItem Foreground="Black" Click="DeleteChecks_Click" Header="Delete Checks" Tag="{Binding CheckType}" Visibility="{Binding Path=OpacityForCCheck,Converter={StaticResource opacityToVisibility}}"/>
<MenuItem Foreground="Black" Header="Goto..." Click="miGoto_Click" Tag="{Binding CheckType}" Visibility="{Binding Path=OpacityForCCheck,Converter={StaticResource opacityToVisibility}}"/>
</ContextMenu>
</local:LightFCCheckBlockControl.ContextMenu>
</local:LightFCCheckBlockControl>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Thanks
Yogaraj I
Well it sounds a bit odd. First of all, you should answer the question...Is it really necessary to bind 1000 items to a list, which should be shown in UI? The usability would not be the best. Perhaps you could choose an approach with deferred loading.
Second, did you disable the Virtualization in the ListBox? Usually, there are only rendered the visuals for the elements, which are visible. The controls will be reused in case of scrolling.

How to style a WPF Expander Header?

I would like to apply a style on a WPF Expander Header. In the following XAML I have an Expander but the style is for all of it not just for the header.
Thanks.
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="640"
>
<StackPanel>
<StackPanel.Resources>
<Style TargetType="Expander">
<Style.Resources>
<LinearGradientBrush x:Key="BackBrush" StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Color="#EF3132" Offset="0.1" />
<GradientStop Color="#D62B2B" Offset="0.9" />
</LinearGradientBrush>
</Style.Resources>
<Setter Property="Background" Value="{StaticResource BackBrush}"/>
</Style>
</StackPanel.Resources>
<Expander>
<StackPanel>
<TextBlock>Bike</TextBlock>
<TextBlock>Car</TextBlock>
<TextBlock>Truck</TextBlock>
</StackPanel>
</Expander>
</StackPanel>
</Page>
I have combined some XAML from Josh Smith and MSDN and came up with a solution. Indeed, the control (al least the header) must be retemplated.
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400">
<StackPanel>
<StackPanel.Resources>
<Style TargetType="Border" x:Key="RacePitBorderStyle" >
<Style.Resources>
<LinearGradientBrush x:Key="BackBrush" StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Color="#EF3132" Offset="0.1" />
<GradientStop Color="#D62B2B" Offset="0.9" />
</LinearGradientBrush>
</Style.Resources>
<Setter Property="Background" Value="{StaticResource BackBrush}"/>
</Style>
<DataTemplate x:Key="titleText">
<Border Style="{StaticResource RacePitBorderStyle}" Height="24">
<TextBlock Text="{Binding}"
Margin="4 0"
VerticalAlignment="Center"
Foreground="White"
FontSize="11"
FontWeight="Normal"
Width="{Binding
RelativeSource={RelativeSource
Mode=FindAncestor,
AncestorType={x:Type Expander}},
Path=ActualWidth}"
TextWrapping="Wrap"/>
</Border>
</DataTemplate>
<Style TargetType="{x:Type Expander}">
<Setter Property="HeaderTemplate" Value="{StaticResource titleText}"/>
</Style>
</StackPanel.Resources>
<Expander Name="hcontCtrl" Header="This is the header.">
<StackPanel>
<TextBox>This is a textbox</TextBox>
<Button>A button</Button>
</StackPanel>
</Expander>
</StackPanel>
</Page>
I think Vasile's answer is on the right track, but it seems like it does a lot more than the original poster needed. All the original question was asking to do was to change the background of the header. While the change presented does do that, it also does other things.
One of these other things is to replace the default implementation, I believe a ContentPresenter, with a TextBlock. So what happens when later we change our Expander so that the header is more complicated? Maybe something like:
<Expander>
<Expander.Header>
<StackPanel>
<Border height="5" width="5" Foreground="Blue"/>
<TextBlock>Ha!</TextBlock>
</StackPanel>
</Expander.Header>
</Expander>
I don't know, but it's not good. Instead, I think we want to keep this simple.
<DataTemplate x:Key="expanderHeader">
<ContentPresenter
Content={Binding}
TextBlock.Background={StaticResource myBrush}/>
</DataTemplate>
<Style TargetType="Expander">
<Setter Property="HeaderTemplate" Value="{StaticResource expanderHeader}"/>
</Style>
That way when someone puts something that is not just text in our styled expander, we don't break. If you want to make sure you wrap the entirety of what they do with this background, which is probably desired, that would look like:
<DataTemplate x:Key="expanderHeader">
<Border Background={StaticResource myBrush}>
<ContentPresenter Content={Binding}/>
</Border>
</DataTemplate>
Depends what you want to style -- you can style any part of it. If you want to change the content in the header, just place all your UI in the Expander.Header property, and it'll show in the header area.
if that does't meet your needs, you probably need to re-template the control. Take a look at the control templates shipped in WPF here

Resources