Popup does not close when scrolling - c#

I have a textbox in which when it has focus a popup appears below it. But when the popup is open and I scroll, it appears to stay in the same spot where it was opened. I need help in figuring out how to have the popup appear below the textbox when I scroll. How would I do this in xaml?
Thanks!
MainWindow View:
<Grid x:Name="LayoutRoot">
<ScrollViewer>
<local:ControlView/>
</ScrollViewer>
</Grid>
Resource Dictionary:
<Style TargetType="{x:Type Popup}">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=txtTest, Path=IsKeyboardFocused}" Value="True">
<Setter Property="IsOpen" Value="True" />
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=txtTest, Path=IsKeyboardFocused }" Value="False">
<Setter Property="IsOpen" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
<Style x:Key="BorderStyle" TargetType="{x:Type Border}">
<Setter Property="Background" Value="LemonChiffon"/>
<Setter Property="Padding" Value="5"/>
</Style>
UserControl View:
<Grid x:Name="LayoutRoot">
<StackPanel Grid.Row="1" Grid.Column="4" Orientation="Vertical">
<Button Content="Button" Width="100" Height="100"/>
<Button Content="Button" Width="100" Height="100"/>
<TextBox x:Name="txtTest" HorizontalAlignment="Stretch"/>
<Popup Name="TestPopup" StaysOpen="True"
PlacementTarget="{Binding ElementName=txtTest}"
AllowsTransparency="True" Placement="{Binding ElementName=txtTest}">
<Border Style="{DynamicResource BorderStyle}">
<GroupBox Header="Test Popup">
<ScrollViewer Margin="0,2,0,0" VerticalScrollBarVisibility="Hidden">
<!--BINDING-->
<Label Content="Hello World!"/>
</ScrollViewer>
</GroupBox>
</Border>
</Popup>
<ContentPresenter Content="{Binding testBinding}"
VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
</ContentPresenter>
</StackPanel>
</Grid>

Try this:
<Style TargetType="{x:Type Popup}">
<Setter
Property="IsOpen"
Value="{Binding IsKeyboardFocusedWithin, ElementName=txtTest, Mode=OneWay}"/>
</Style>

Related

Change Background Color of SelectedItem from WPF ListView with Custom DataTemplate

I have a ListView Control in WPF which displays a list of boxes from which the user can select one from the collection. What I'm currently trying to accomplish is to have Selected Item's Background Property changed to a different color for a proper identification.
I found a Code Snippet which partially solves my problem, however, the Background value of the SelectedItem reverts back to its original when I press anywhere within the module.
What I'd like to happen is for the Background value to persist for the SelectedItem regardless if I press on other controls or even if the Window gets unfocused.
Below is my XAML Code Snippet with the Setters and Triggers I currently have in place.
<ListView Grid.Row="2"
ItemsSource="{Binding FakeDispatchBoxCollection}">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<ContentPresenter />
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter Property="IsSelected" Value="True" />
</Trigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate>
<md:Card Margin="0,0,0,10"
Cursor="Hand">
<md:Card.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsSelected, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListViewItem}}}" Value="true">
<Setter Property="md:Card.Background" Value="LightGray" />
</DataTrigger>
</Style.Triggers>
</Style>
</md:Card.Style>
<Grid Margin="5">
<!--#region Row & Column Definitions -->
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.60*" />
<ColumnDefinition Width="0.40*" />
</Grid.ColumnDefinitions>
<!--#endregion-->
<Label Grid.Row="0" Grid.Column="0"
Content="{Binding DispatchBoxName}"
FontWeight="ExtraBlack"
FontSize="15"
FontFamily="Baloo Bhai 2" />
<Label Grid.Row="1" Grid.Column="0"
Content="{Binding DispatchBoxType}"
FontWeight="SemiBold"
FontSize="13"
FontFamily="Baloo Bhai 2" />
<Label Grid.Row="0" Grid.Column="1"
Grid.RowSpan="2"
Content="{Binding UnitCount}"
VerticalAlignment="Center"
HorizontalAlignment="Right"
FontWeight="ExtraBlack"
FontSize="20"
FontFamily="Baloo Bhai 2" />
</Grid>
</md:Card>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
In the Item's Data Template (ItemTemplate property), you don't have any items that can accept keyboard focus. There are only Labels.
And in the ListViewItem Template Trigger (ItemContainerStyle property), you set the IsSelected property dependency on the keyboard focus inside the ListViewItem.
Also, you shouldn't use a ListView if you don't specify columns. In this case it is better to use ListBox.
An example of a correct implementation:
<Window.Resources>
<!--To simplify the example.-->
<CompositeCollection x:Key="source">
<sys:String>First</sys:String>
<sys:String>Second</sys:String>
<sys:String>Third</sys:String>
<sys:String>Fourth</sys:String>
</CompositeCollection>
</Window.Resources>
<ListBox ItemsSource="{DynamicResource source}">
<ItemsControl.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<ContentPresenter />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Label x:Name="label" Content="{Binding}"/>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Path=IsSelected, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}}}"
Value="true">
<Setter TargetName="label" Property="Background" Value="Coral" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ListBox>

How to design this ListViewItem

I want my ListViewItem to look like this. As you can see when the ListViewItem is selected/has focus the Border should change color.
The Main Problem is that I can't put a Border around the ContenPresenter in the ControlTemplate because than also the TextBox with the "Description"-Binding will be inside the Border. But I only want the TextBox and Icon to be inside the Border that changes Colors and not also the Description ("Nachname", "Vorname").
This is the XAML I have so far. I don't know how to change the border in the ControlTemplate:
<ListView x:Name="SearchFields" Grid.Row="0" Grid.Column="0" ItemsSource="{Binding CustomerSearchFields}" SelectedItem="{Binding selectedSearchField, UpdateSourceTrigger=LostFocus}" Style="{StaticResource MaterialDropShadowStyle}"
BorderThickness="0,0,2,0" Padding="24,24,24,0" HorizontalContentAlignment="Stretch" helper:EnterKeyTraversal.IsEnabled="True" KeyboardNavigation.TabNavigation="Cycle" FontFamily="{StaticResource DefaultFontFamily}"
Background="{StaticResource ColorLightGray2}">
<ListView.Resources>
<DataTemplate DataType="{x:Type model:CustomerSeachFieldViewModel}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="48" />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="{Binding Description}" FontSize="{StaticResource FontSizeSmall}" FontWeight="SemiBold" Foreground="{StaticResource ColorDarkGray}" Margin="0,0,0,4" />
<Border x:Name="PART_Border" Grid.Row="1" BorderThickness="1" BorderBrush="{StaticResource ColorGray}">
<Grid Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="48" />
</Grid.ColumnDefinitions>
<TextBox Grid.Column="0" Text="{Binding SearchText}" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" FontSize="{StaticResource FontSizeNormal}" Padding="12,15" BorderThickness="0" />
<Border Grid.Column="1" Background="{StaticResource ColorLightGray2}" Margin="8">
<ctrl:IconViewbox IconData="{StaticResource IconPathSearch}" IconSize="16" IsTabStop="False" />
</Border>
</Grid>
</Border>
</Grid>
</DataTemplate>
</ListView.Resources>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="IsTabStop" Value="False" />
<Setter Property="Margin" Value="0,0,0,24" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<ContentPresenter Content="{Binding}" />
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter Property="IsSelected" Value="True" />
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Trigger.Setters>
<Setter Property="BorderBrush" Value="Fuchsia" />
</Trigger.Setters>
</Trigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
</ListView>
You can add a Trigger to your Border named PART_Border as follow:
<Border x:Name="PART_Border" Grid.Row="1" BorderThickness="1" >
<Border.Style>
<Style TargetType="Border">
<Setter Property="BorderBrush" Value="DarkGray" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListViewItem}}}"
Value="True" >
<Setter Property="BorderBrush" Value="Black"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<Grid Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="48" />
</Grid.ColumnDefinitions>
<TextBox Grid.Column="0"
Text="{Binding SearchText}" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" FontSize="15" Padding="12,15" BorderThickness="0" />
<Border Grid.Column="1" Background="Gray" Margin="8">
<Rectangle Width="20" Height="20" />
</Border>
</Grid>
</Border>
Please note that I replaced some StaticResource mapped to some Colors from your code with standard color in order to test my code.
I also replaced the icon with a Rectangle for the same reason.
Try for your IsSelected trigger:
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="PART_Border" Property="BorderBrush" Value="Fuchsia" />
<Setter TargetName="PART_Border" Property="BorderThickness" Value="1" />
</Trigger>
You could add a Style with a DataTrigger that binds to the IsSelected property of the parent ListViewItem to the Border in your DataTemplate:
<Border x:Name="PART_Border" Grid.Row="1" BorderThickness="1">
<Border.Style>
<Style TargetType="Border">
<Setter Property="BorderBrush" Value="{StaticResource ColorGray}" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=ListViewItem}}"
Value="True">
<Setter Property="BorderBrush" Value="Red" />
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
</Border>
Note that you need to set the default value of the property ({StaticResource ColorGray}) using a Style setter for the DataTrigger to be able to set the property when the ListViewItem is selected.

User control missing buttons when placed on main window

I have the main window which consists of 2 columns (in a grid), on the left side there is a map (Microsoft Bing) and on the right side I want to create some sort of config panel.
I have created a UserControl that is meant to show some statistics and configure capabilities
This is how the user control is supposed to look, and This is how it looks like when I run the program. As you can see, labels,buttons and textboxes are missing from the top part.
Here is the usercontrol's code:
<UserControl x:Class="WEI.UserControls.MapTab"
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:local="clr-namespace:WEI.UserControls"
mc:Ignorable="d"
d:DesignHeight="600" d:DesignWidth="300" >
<Grid Background="AliceBlue">
<TabControl Margin="5" BorderBrush="Gainsboro">
<TabControl.Resources>
<Style TargetType="TabItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TabItem">
<Border Name="Border" BorderThickness="1,1,1,0" BorderBrush="Gainsboro" CornerRadius="4,4,0,0" Margin="2,0">
<ContentPresenter x:Name="ContentSite"
VerticalAlignment="Center"
HorizontalAlignment="Center"
ContentSource="Header"
Margin="10,2"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Border" Property="Background" Value="LightSkyBlue" />
</Trigger>
<Trigger Property="IsSelected" Value="False">
<Setter TargetName="Border" Property="Background" Value="GhostWhite" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</TabControl.Resources>
<TabItem Header="General">
<Grid>
<Button Margin="82,126,95,392" x:Name="setCoordinates" Content="Go to coordinate" FontSize="10" />
<Button Margin="82,190,95,328" x:Name="addMark" Content="Add mark" FontSize="10" />
<TextBox x:Name="Latitude" Margin="41,52,173,479"/>
<TextBox x:Name="Longitude" Margin="161,53,54,478"/>
<Label Content="Latitude" Margin="41,18,173,513" />
<Label Content="Longitude" Margin="160,17,54,513" />
<Separator/>
<Border BorderBrush="AliceBlue" BorderThickness="1" Margin="88,348,95,83">
<TextBlock TextWrapping="Wrap" Margin="-1" Text="" VerticalAlignment="Center" Height="130" />
</Border>
<Label Content="Active targets" HorizontalAlignment="Left" Margin="96,299,0,0" VerticalAlignment="Top"/>
</Grid>
</TabItem>
<TabItem Header="Statistics" >
</TabItem>
<TabItem Header="Details" />
</TabControl>
</Grid>
</UserControl>

WPF listbox empty item template not showing

I am try to list some data in WPF listbox control. It is the first time I am using DataTemplate in WPF. Everything is working fine except when there is no data it is not showing 'No items to display'. Below is my code.
<ListBox Name="itemsCtrl" Background="#FFE5E5E5" BorderBrush="{x:Null}" SelectionChanged="itemsCtrl_SelectionChanged" Style="{StaticResource ListStyle}">
<ListBox.Resources>
<!-- Set SelectedItem Background here -->
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="#C2C2C2"/>
<Style TargetType="{x:Type ListBoxItem}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsMouseOver,
RelativeSource={RelativeSource
Self}}"
Value="True">
<Setter Property="Background"
Value="#C2C2C2" />
</DataTrigger>
</Style.Triggers>
</Style>
<Style TargetType="ListBox" x:Key="ListStyle" BasedOn="{StaticResource {x:Type ListBox}}">
<Style.Triggers>
<DataTrigger
Binding="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=Items.Count}"
Value="0"
>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<TextBlock>No items to display</TextBlock>
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</ListBox.Resources>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Cursor="Hand" Name="hoverDataTemplate" Orientation="Horizontal" Width="370" VerticalAlignment="Top" Height="40" HorizontalAlignment="Left" >
<Label VerticalContentAlignment="Center" HorizontalAlignment="Left" Padding="15,5,5,5" Width="330" Content="{Binding Path=EVENT_TITLE}" FontSize="12"/>
<Image Height="28" Source="/pr;component/Images/black_next.png" Stretch="Fill" Width="28" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
And I am binding data source as shown below.
itemsCtrl.ItemsSource = dao.SelectDataTable(cmd).DefaultView;
When I set the style property of ListBox as ListStyle it is throwing an error
'Provide value on 'System.Windows.StaticResourceExtension' threw an exception.' Line number '292' and line position '22'.
Can anybody point out how to make it correct?
Thanks in advance.
i have used below code and it's work fine
my xaml code
<ListBox Grid.ColumnSpan="2" Grid.Row="1" Height="32" HorizontalAlignment="Left" Margin="160,2,0,0" Name="listBox1" VerticalAlignment="Top" Width="120" Style="{StaticResource Dhaval}"/>
Style look like
<Style x:Key="Dhaval" TargetType="{x:Type ListBox}">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Items.Count}" Value="0">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<TextBlock>No items to display</TextBlock>
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>

WPF StackPanel Layout Question

I'm trying to create a layout similar to this:
alt text http://img20.imageshack.us/img20/3533/stackn.png
Here's the code I have:
<StackPanel TextBlock.FontFamily="Segoe UI" Orientation="Horizontal">
<StackPanel HorizontalAlignment="Stretch" Width="Auto">
<TextBlock Padding="5,0,5,0" FontSize="12" FontWeight="Bold" Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Title}" />
<TextBlock Padding="5,0,5,0" FontSize="12" Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Id}" />
</StackPanel>
<StackPanel>
<TextBlock Padding="5,0,5,0" FontSize="10" Text="Delete">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="FontWeight" Value="Bold" />
</Trigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<TextBlock Padding="5,0,5,0" FontSize="10" Text="Move">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="FontWeight" Value="Bold" />
</Trigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</StackPanel>
</StackPanel>
Why don't you use a Grid for this?
<Grid x:Name="LayoutRoot" Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="300" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0">
<TextBlock Text="{Binding Title}" />
</StackPanel>
<StackPanel Grid.Column="1">
<TextBlock Text="Move" />
</StackPanel>
</Grid>
I think you might be better off with a grid as your parent element. Omitting your styles and what not, here's the XAML for the layout in your drawing.
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="50" /> <!-- or some other fixed width -->
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0">
<!-- left hand stackpanel content -->
</StackPanel>
<StackPanel Grid.Column="1">
<!-- right hand StackPanel content -->
</StackPanel>
</Grid>
You don't really want a StackPanel for your red container. I'd go with a DockPanel, dock the rightmost blue panel to the right, and ensure LastChildFill is on to ensure the leftmost blue panel expands to the window width.
Here is the code for what I get from your post:
<DockPanel TextBlock.FontFamily="Segoe UI" LastChildFill="True">
<StackPanel DockPanel.Dock="Right">
<TextBlock Padding="5,0,5,0" FontSize="10" Text="Delete">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="FontWeight" Value="Bold" />
</Trigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<TextBlock Padding="5,0,5,0" FontSize="10" Text="Move">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="FontWeight" Value="Bold" />
</Trigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</StackPanel>
<StackPanel HorizontalAlignment="Stretch" Width="Auto">
<TextBlock Padding="5,0,5,0" FontSize="12" FontWeight="Bold" Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Title}" />
<TextBlock Padding="5,0,5,0" FontSize="12" Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Id}" />
</StackPanel>
</DockPanel>
Hope this helps!!

Categories

Resources