Binding popup PlacementTarget to listbox SelectedItem - c#

I have the following XAML (simplified):
<Grid>
<Popup Name="Popup" DataContext="{Binding ElementName=GameWheel, Path=SelectedItem}" PlacementTarget="{Binding SelectedItem}" Placement="Center" IsOpen="True">
<Image Source="{Binding ImagePath}" Width="100" />
</Popup>
<DockPanel Margin="40,0">
<ListBox x:Name="GameWheel" ...>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<c:VirtualizingWrapPanel IsItemsHost="True" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Image x:Name="GamesWheelImage" ... />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DockPanel>
</Grid>
While the DataContext is correct and it shows me the right image in the popup, the placement is completely wrong. My intention is to have the popup cover the center of the SelectedItem in the listbox, but for some reason it's always placed in the center of the window.
Any ideas on how to get the placement for the selectedItem in the listbox so the popup always covers the center of the selected item? The closest I get it to place the image in the center of the listbox, but I'm not able to get it to cover just the selected item.

In my opinion you should create a specific template for the ListBoxItems which belong to the Listbox called GameWheel.
Just to give you a sample, I created a simplier version of your ListBox:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
Title="MainWindow" Height="300" Width="400">
<Window.Resources>
<ControlTemplate x:Key="ListBoxItemWithPopup" TargetType="{x:Type ListBoxItem}">
<Border Name="border" Padding="2">
<Grid>
<Popup Name="popup" PlacementTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}"
Placement="Center" >
<TextBlock Margin="1" Background="White" Foreground="Black" Text="{TemplateBinding Content}" />
</Popup>
<ContentPresenter />
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter TargetName="popup" Property="IsOpen" Value="True"/>
<Setter TargetName="border" Property="Background" Value="Azure" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Window.Resources>
<Grid>
<DockPanel Margin="40,0">
<ListBox x:Name="GameWheel">
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Template" Value="{StaticResource ListBoxItemWithPopup}" />
</Style>
</ListBox.ItemContainerStyle>
<ListBox.Items>
<sys:String>One</sys:String>
<sys:String>Two</sys:String>
<sys:String>Three</sys:String>
<sys:String>Four</sys:String>
</ListBox.Items>
</ListBox>
</DockPanel>
</Grid>
</Window>
As you can see the Popup is directly contained in the ListBoxItem template and it is showed using a Trigger.
I hope my sample can help you.

Related

Wpf : How to make a letter pop out of the border

how do make a letter pop out of the border?
I want to express it like this picture
I wrote a letter in the text on Border,
The letters are covered like in the picture.
Can you make this stick out like the picture below?
How can solve this?
this is my xaml code
<Window x:Class="TestProject.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TestProject"
Width="800"
Height="600"
Title="ItemsControl 엘리먼트 : Template/ItemsPanel/ItemTemplate/ItemContainerStyle 속성 사용하기"
FontFamily="나눔고딕코딩"
FontSize="16">
<Window.Resources>
<local:TaskCollection x:Key="TaskCollectionKey" />
</Window.Resources>
<Grid>
<ItemsControl
HorizontalAlignment="Center"
VerticalAlignment="Center"
ItemsSource="{Binding Source={StaticResource TaskCollectionKey}}">
<ItemsControl.Template>
<ControlTemplate TargetType="ItemsControl">
<Border
BorderBrush="Black"
BorderThickness="3"
CornerRadius="15">
<ItemsPresenter />
</Border>
</ControlTemplate>
</ItemsControl.Template>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<DataTemplate.Resources>
<Style TargetType="TextBlock">
<Setter Property="HorizontalAlignment" Value="Center" />
</Style>
</DataTemplate.Resources>
<Grid>
<Ellipse
Stroke="Black"
StrokeThickness="3"
Fill="Gold" />
<StackPanel
HorizontalAlignment="Center"
VerticalAlignment="Center">
<TextBlock
Margin="5"
Text="{Binding Path=Priority}" />
<TextBlock
Margin="5"
Text="{Binding Path=TaskName}" />
</StackPanel>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="Control.Margin" Value="10" />
<Setter Property="Control.Width" Value="100" />
<Setter Property="Control.Height" Value="100" />
<Style.Triggers>
<Trigger
Property="Control.IsMouseOver" Value="True">
<Setter Property="Control.ToolTip"
Value="{Binding RelativeSource={x:Static RelativeSource.Self},
Path=Content.Description}" />
</Trigger>
</Style.Triggers>
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
</Grid>
</Window>
If you put the textblock in a canvas, that will not clip.
<StackPanel
HorizontalAlignment="Center"
VerticalAlignment="Center">
<TextBlock
Margin="5"
Text="{Binding Path=Priority}" />
<Canvas>
<TextBlock
Text="{Binding Path=TaskName}" />
</Canvas>
</StackPanel>

WPF Particular TabItem Width Behaviour

I've this code with TabItems added Dynamycally in CodeBehind (C#):
<TabControl x:Name="tabList" Grid.Column="2" HorizontalContentAlignment="Stretch" Background="Transparent" SelectionChanged="tabList_SelectionChanged" IsSynchronizedWithCurrentItem="True">
<TabControl.Resources>
<DataTemplate x:Key="TabHeader" DataType="TabItem">
<DockPanel>
<Button x:Name="btnDelete" BorderThickness="0" Background="Transparent" DockPanel.Dock="Right" Margin="5,0,0,0" Padding="0" Click="btnDelete_Click" CommandParameter="{Binding RelativeSource={RelativeSource AncestorType={x:Type TabItem}}, Path=Name}">
<Image Source="myImage></Image>
</Button>
<ToggleButton x:Name="btnPin" Checked="btnDisablex" Unchecked="btnDisablex" BorderThickness="0" Background="Transparent" DockPanel.Dock="Right" Margin="5,0,0,0" Padding="0" CommandParameter="{Binding RelativeSource={RelativeSource AncestorType={x:Type TabItem}}, Path=Name}">
<ToggleButton.Style>
//Many Useless Things
</ToggleButton.Style>
</ToggleButton>
<TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type TabItem}}, Path=Header}" />
</DockPanel>
</DataTemplate>
<Style TargetType="TextBox">
//Other Many Useless Things
</Style>
</TabControl.Resources>
</TabControl>
And with the following Style in User Resources:
<Style TargetType="{x:Type TabItem}">
<Setter Property="AllowDrop" Value="True"/>
<EventSetter Event="PreviewMouseMove" Handler="TabItem_PreviewMouseMove"/>
<EventSetter Event="Drop" Handler="TabItem_Drop"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid>
<Border
Name="Border"
Margin="0,0,-4,0"
Background="White"
BorderBrush="#888"
BorderThickness="1,1,1,1"
CornerRadius="2,12,0,0">
<ContentPresenter x:Name="ContentSite"
VerticalAlignment="Center"
HorizontalAlignment="Center"
ContentSource="Header"
Margin="12,2,12,2"
RecognizesAccessKey="True"/>
</Border>
</Grid>
<ControlTemplate.Triggers>
//Many Useless MultiTrigger and Datatrigger
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The code is working fine, until I add more tabs and the window width is no longer enough, but the TabControl behaviour is strange: the TabItem width becomes larger and the first TabItems disappear.
I just want the TabItem width reduces or just that the olders "disappear" but keeping always the same width. Why this is not working?
This is the screenshot taken in normal conditions
Normal view working OK
Here it's clear the problem: when I add more tabs (or I reduce the window/grid width) the tab width becomes larger
Tab View Problem

change color of the tab control panel background

I have a TabControl like so:
<TabControl ItemsSource="{Binding TabItems, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
SelectedIndex="0"
BorderThickness="0"
TabStripPlacement="Left"
Padding="10,0,0,10">
<TabControl.ItemContainerStyle>
<Style TargetType="TabItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TabItem">
<Grid Name="Panel">
<ContentPresenter x:Name="ContentSite" VerticalAlignment="Center" HorizontalAlignment="Center" ContentSource="Header" Margin="20,5"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Panel" Property="Background" Value="#d9534f" />
</Trigger>
<Trigger Property="IsSelected" Value="False">
<Setter TargetName="Panel" Property="Background" Value="#E6E3DB" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Header" Value="{Binding Header, Mode=OneTime}"/>
<Setter Property="Content" Value="{Binding Content, Mode=OneTime}"/>
</Style>
</TabControl.ItemContainerStyle>
</TabControl>
Is there a way to change the color of the Panel where TabItems are located:
Thank you for any suggestions.
EDIT after OP clarified the question.
The are you refer to has nothing to do with the TabItem or even the TabControl. It's simply the control where the TabControl resides in.
Please see the following simple example:
<Window x:Class="StackOverflowWPF.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:StackOverflowWPF"
mc:Ignorable="d"
Title="MainWindow" Height="200" Width="300">
<Grid Background="LightSeaGreen">
<TabControl Background="Red">
<TabItem Header="Tab1" Background="Yellow">
</TabItem>
<TabItem Header="Tab1" Background="Green">
</TabItem>
</TabControl>
</Grid>
</Window>
And this is what it looks like in the designer:
So going back to your example, I'm assuming you want to set the color of area pointed to by an arrow, while keeping the rest of the form in a different color. I'd make use of the Grid control for that.
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid Grid.Row="0" Background="LightGreen">
<TabControl Grid.Row="0" Background="Red" Height="100">
<TabItem Header="Tab1" Background="Yellow">
</TabItem>
<TabItem Header="Tab1" Background="Green">
</TabItem>
</TabControl>
</Grid>
<Grid Grid.Row="1"/>
</Grid>
And it will look like this:

ListBox ItemSource binding asks for Dependency property from unknown reason

Hi I have the following UserControl.
Can notice that in the second HierarchicalDataTemplate contains also a ListBox.
I would like the ListBox ItemsSource to bind to the a field in the viewModel taht is CurrentPropertyValues .
When I try to bind it in the mainwindow or just outside the tree, it works, (just ItemsSource="{Binding CurrentPropertyValues}")
I tried various things to make it work inside the HierarchicalDataTemplate (it has a different data context) but I keep on failing.
Thanks for any help!
<UserControl x:Class="RidaDiff2.Views.LeftTreeControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:converters="clr-namespace:RidaDiff2.Converters"
xmlns:model="clr-namespace:RidaDiff2.Model"
xmlns:viewModel="clr-namespace:RidaDiff2.ViewModels"
xmlns:views="clr-namespace:RidaDiff2.Views"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Resources>
<converters:EnumToPicConverter x:Key="Converter" />
<HierarchicalDataTemplate DataType="{x:Type model:TreeNode}" ItemsSource="{Binding ChildListNodes}" x:Key="NotSelected">
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Path=EntityType,Converter={StaticResource Converter}}" />
<TextBlock Margin="5,0" Text="{Binding Name1}" />
<!--"{Binding ItemName, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" -->
</StackPanel>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type model:TreeNode}" ItemsSource="{Binding ChildListNodes}" x:Key="Selected">
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Path=EntityType,Converter={StaticResource Converter}}" />
<TextBlock Margin="5,0" Text="{Binding Name1}" />
</StackPanel>
<ListBox DataContext="viewModel:TreeViewModel" Height="300" Width="100" ItemsSource="{Binding Path=(viewModel:TreeViewModel.CurrentPropertyValues), Mode=TwoWay}" ></ListBox>
</StackPanel>
</HierarchicalDataTemplate>
</UserControl.Resources>
<views:ExtendedTreeView x:Name="Tree" ScrollViewer.VerticalScrollBarVisibility="Auto" ItemsSource="{Binding RootNode}" SelectedItem_="{Binding CurrentCouple,Mode=TwoWay}">
<views:ExtendedTreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsExpanded" Value="{Binding Path=(model:TreeNode.IsExpanded), Mode=TwoWay}" />
<Setter Property="Background" Value="{Binding Path=(model:TreeNode.BackgroundColor), Mode=TwoWay}" />
<Setter Property="IsSelected" Value="{Binding Path=(model:TreeNode.IsSelected), Mode=TwoWay}"></Setter>
<Setter Property="HeaderTemplate" Value="{StaticResource NotSelected}"/>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="HeaderTemplate" Value="{StaticResource Selected}"/>
</Trigger>
</Style.Triggers>
</Style>
</views:ExtendedTreeView.ItemContainerStyle>
</views:ExtendedTreeView>
If CurrentPropertyValues is a property of TreeViewModel then you can use RelativeSource binding and go up the visual tree to find TreeView and bind ItemsSource to property of its DataContext:
<ListBox
Height="300"
Width="100"
ItemsSource="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type TreeView}}, Path=DataContext.CurrentPropertyValues}" />

Could someone give me some adviceabout WPF?

I am making a user control that is databound. The query results include a collection of objects (A) where A has a collction of other results (B). So A contains multilple B.
in the user control I want to represent the collection A as expanders and B as buttons inside of the expanders. This is what I got
<UserControl x:Class="GuideLib.ModuleControls.uclQuestions"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<ItemsControl x:Name="ictlAnswers" ItemsSource="{Binding}" Background="Gray">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Expander ExpandDirection="Down" Background="DarkGray">
<Expander.Header>
<TextBlock Text="{Binding Path=Name}" Foreground="White"/>
</Expander.Header>
<ListBox x:Name="SubListBox" ItemsSource="{Binding Path=Question}" Background="Gray" Foreground="White" HorizontalAlignment="Stretch">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Stretch">
<Button Content="{Binding Path=Name}" Margin="10,2,2,2" HorizontalAlignment="Stretch" Tag="{Binding Path=ID}">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="Gray" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Orange" />
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Expander>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
I have multiple problems.
1: I can not get the buttons in the expanders to strech horizontally
2: How can I set the Tag property of the button to be the whole object of B
3: Why does the default mouseover effect still execute.
Thanks
Ok here goes:
1. You need to set HorizontalContentAlignment="Stretch" on the ListBox and on the StackPanel inside DataTemplate set Orientation="Vertical"
2. set Tag="{Binding .}" on the Button
3. Update your Button.Style to something like:
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Background"
Value="Gray" />
<Setter Property="OverridesDefaultStyle"
Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Background="{TemplateBinding Background}">
<ContentPresenter />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver"
Value="True">
<Setter Property="Background"
Value="Orange" />
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
finally before you add Question 4. remember ListBoxItem has a Style of it's own. So to completely override the effect on MouseOver when not on the Button but in the "Item" you have to provide a custom Style for ListBox.ItemContainerStyle
Oh and Start Using Snoop. It helps you debug Layout issues. Think you would have been able to solve problem 1 with it cos it would have shown you that your ContentPresenter of ListBoxItem was using required Width and not Stretching.
Just from taking a quick look at it.. for question 2 try doing this:
<Button Content="{Binding Path=Name}" Margin="10,2,2,2" HorizontalAlignment="Stretch" Tag="{Binding}">
That should make it bind to the items in the ListBox.

Categories