I have a FrameworkElement (really a ToggleButton) that has inside its content a Popup.
I access it like this:
ToggleButton button = (ToggleButton)sender;
Popup popup = (Popup)button.FindName("popSelectIteration");
Usually this works fine. But sometimes popup is null.
I am trying to find a way to debug this. Is there a way enumerate all the "things" that FindName could find?
As background, here is how my popup is defined in the ToggleButton:
<ToggleButton Grid.Column="1" HorizontalAlignment="Right" Margin="0,2,0,2" Checked="btnFindIterationChecked">
<Grid>
<Popup PlacementTarget="{Binding ElementName=chkIteration}" Name="popSelectIteration" Closed="popSelectIteration_Closed"
AllowsTransparency="True" StaysOpen="False" PopupAnimation="Fade">
<Border BorderBrush="#FF000000" Background="LightBlue" BorderThickness="1,1,1,1" CornerRadius="8,8,8,8" Padding="5">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="300"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<TextBlock Foreground="Black" >Select Destination:</TextBlock>
<ScrollViewer Grid.Row="1" >
<TreeView ItemsSource="{Binding IterationTree}" SelectedItemChanged="TreeView_SelectedItemChanged">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding PathEnd}" />
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</ScrollViewer>
<Button Grid.Row="2" Background="LightBlue" Content="Clear Selection" Click="btnClear_Click"/>
</Grid>
</Border>
</Popup>
</Grid>
</ToggleButton>
Try Snoop. It is a great WPF debugging utility for everything that concerns the visual tree.
Edit: Your specific problem seems to be a timing issue though. I guess that the tree is not completely constructed yet and you try to access a child element although it is not created. Wait until the topmost element receives a "Loaded" event.
Related
I'm sorry if I didn't find any relative post/questions regarding my small annoying issue.
I have a WPF window with a DockPanel (LastChildFill = True) that hosts three controls :
One Button (OK)
One label (Title)
One Border with a listbox in it
What I do is when the test in process is "pass" it has no data to push in the listbox so I make it collapsed and then I would like the Title label to be centered in the available space that is not used by the listbox and its border.
When I have a "fail" or an "error", I have data to put in the listbox and then it is visible and everything is just as expected.
I tried many things before coming here and I lost enough time on this as I need to get other stuff done by the time I'm writing here.
Can anyone point me out how to solve my issue (centering label when listbox+border is collapsed) ?
Here is my xaml code for this window :
<Window x:Class="NI.TestStand.WPFControls.Views.DisplayBannerView"
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:NI.TestStand.WPFControls"
mc:Ignorable="d"
Title="DisplayBanner" x:Name="DisplayBannerMessage" Height="500" Width="800" MinHeight="300" MinWidth="500">
<Window.Resources>
<Style x:Name="BaseWindowFont" TargetType="Window">
<Setter Property="FontFamily" Value="Arial"></Setter>
<Setter Property="FontSize" Value="16"></Setter>
</Style>
</Window.Resources>
<Grid>
<Border BorderBrush="Black" BorderThickness="2">
<DockPanel LastChildFill="True">
<Button
x:Name="butOK"
DockPanel.Dock="Bottom"
Margin="10" Content="OK"
HorizontalAlignment="Center"
VerticalAlignment="Top"
Padding="10" Width="150"
Click="butOK_Click"/>
<Label
x:Name="main_message"
Padding="15"
FontSize="50"
Content="MAIN_MSG"
DockPanel.Dock="Top"
HorizontalAlignment="Center"
VerticalContentAlignment="Center" />
<Border BorderBrush="Chocolate" BorderThickness="2" Margin="10" Name="messages_border">
<ListBox
Background="{Binding ElementName=DisplayBannerMessage, Path=Background}"
Foreground="Black"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
ScrollViewer.VerticalScrollBarVisibility="Auto"
ScrollViewer.CanContentScroll="True"
VerticalContentAlignment="Top"
VerticalAlignment="Stretch"
x:Name="detail_message">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" ToolTip="{Binding}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Border>
</DockPanel>
</Border>
</Grid>
</Window>
Here are the images that shows a PASS and an ERROR to show the difference.
The PASSED title message in the green lime window should go in the middle of the window as the listbox is collapsed..
Thanks for all your help and time
I would design the whole thing like this:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Border BorderBrush="Black" BorderThickness="2"
Grid.RowSpan="{Binding PassErrorBooleanProperty, Converter={StaticResource BoolToRowSpanConverter}}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Label
x:Name="main_message"
Padding="15"
FontSize="50"
Content="MAIN_MSG"
DockPanel.Dock="Top"
HorizontalAlignment="Center"
VerticalContentAlignment="Center" />
<Border Grid.Row="1" BorderBrush="Chocolate" BorderThickness="2" Margin="10" Name="messages_border"
Visibility="{Binding PassErrorBooleanProperty, Converter={StaticResource BoolToVisibilityConverter}}">
<ListBox
Background="{Binding ElementName=DisplayBannerMessage, Path=Background}"
Foreground="Black"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
ScrollViewer.VerticalScrollBarVisibility="Auto"
ScrollViewer.CanContentScroll="True"
VerticalContentAlignment="Top"
VerticalAlignment="Stretch"
x:Name="detail_message">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" ToolTip="{Binding}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Border>
<Button Grid.Row="2"
x:Name="butOK"
DockPanel.Dock="Bottom"
Margin="10" Content="OK"
HorizontalAlignment="Center"
VerticalAlignment="Top"
Padding="10" Width="150"
Click="butOK_Click" />
</Grid>
</Border>
</Grid>
There are two bindings to PassErrorBooleanProperty (which I've made up as something you'd use to indicate the result, you might have something else in place for this already), and you'd need two different converters, one for converting to a Visibility, and one for converting to an int (Grid.RowSpan).
When the value is true (Pass), you'd return Visibility.Collapsed and 2 from the converters. When the value is false, you'd return Visibility.Visible and 1.
Let me know if you need more info on the converters, though there is lots of information out there on using IValueConverter to create Boolean to Visibility converters, etc.
I made a popup control that can accept any view of type FrameworkElement. In addition, you can provide a view model, which will be bound to the DataContext of the child view being provided. Everything works, but it takes a couple of seconds to render the data. The view model has an ObservableCollection that contains about 300 items. So in all honesty, 300 items shouldn't cause any issues.
There is no lag what so ever, If I extract the xaml from the popup to a regular page.
So, is there something inside a Popup control that happens when it's Child content property is being set, that would cause such a delay? Because this is blowing my mind at the moment.
Thanks in advance!
[Update]
As requested, the XAML that forms the child content of the tool window:
<UserControl
x:Class="App.Controls.ContactSelector"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
xmlns:core="using:Microsoft.Xaml.Interactions.Core"
mc:Ignorable="d" x:Name="contactSelector"
DataContext="{Binding ContactSelectorViewModel,Source={StaticResource Locator}}">
<Grid HorizontalAlignment="Stretch" Style="{StaticResource BaseGridStyle}">
<Grid.RowDefinitions>
<RowDefinition Height="1*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ListView Grid.Row="0" ItemsSource="{Binding ContactCollection}">
<ListView.ItemTemplate>
<DataTemplate>
<Grid Margin="12">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<!--<Image Margin="0,0,10,0" Grid.Row="0" Grid.Column="0"
Source="{Binding Thumbnail}" MaxHeight="35"
Visibility="{Binding Thumbnail, Converter={StaticResource ObjectNullToVisibilityConverter}}" />-->
<!--<Image Margin="0,5,5,5" Grid.Row="0" Grid.Column="0" MaxHeight="35"
Source="ms-appx:///Assets/Images/Contact.png"
Visibility="{Binding Thumbnail, Converter={StaticResource InverseObjectNullToVisibilityConverter}}" />-->
<TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding FullName}"
VerticalAlignment="Center"
Style="{StaticResource TextBlockMedium}" />
<!--<Grid Grid.Row="1" Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ItemsControl Grid.Row="0" ItemsSource="{Binding MobileNumbers}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Margin="10,5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Margin="0"
Text="{Binding Number}"
HorizontalAlignment="Stretch"
Style="{StaticResource TextBlockMedium}">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Tapped">
<core:InvokeCommandAction
Command="{Binding DataContext.SelectContact, ElementName=contactSelector}"
CommandParameter="{Binding}" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</TextBlock>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>-->
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
<!--<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<Border>
<TextBlock Text="{Binding Key}"
VerticalAlignment="Center" HorizontalAlignment="Center"
Style="{StaticResource TextBlockMedium}"
Padding="5" Margin="5" FontWeight="SemiBold" />
</Border>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListView.GroupStyle>-->
</ListView>
</Grid>
</UserControl>
So I have commented out the entire section of the ItemsControl, but this did not solve the problem. When the Popup opens, it still takes quite a while to show the containing items.
It isn't slow when it's scrolling, it's slow in rendering the initial items.
The problem is in the ItemsControl which displays the MobileNumbers collection. You should not have an ItemsControl as an ItemTemplate for another ItemsControl (in your case, the ListView). You can do that only when you display small amount of items.
Because of this your MobileNumbers items are not virtualized and this is where the performance problem comes from, as all the items need to be displayed to render the item template.
You can try creating a flat list of objects, and then use ItemTemplateSelector to display different item templates for different types. For example you could have the following ObservableCollection as the ItemsSource:
Header
Contact info
Mobile number1
Mobile number2
Header
Contact info
Mobile number
etc.
<Grid Margin="3,0,3,3">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="20"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<DockPanel Grid.Row="0">
<Image Source="/Images/Search.ico" Height="20" Width="20" DockPanel.Dock="Right"></Image>
<dxe:TextEdit ValidateOnTextInput="True" EditValueChanged="TextEdit_EditValueChanged"/>
</DockPanel>
<ListBox Name="ShortName_ListBox" Grid.Row="1" BorderThickness="0" VirtualizingPanel.IsVirtualizing="True" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" MouseLeftButtonDown="ListBox_Selection" Cursor="Hand"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Grid>
Here is my code. I successfully getting my result when I click on TextBlock(When Hand cursor appear)in ListBox.But when ListBoxItem is selected without touching to TextBlock only touch to the border of ListBoxItem it make that item selected but MouseLeftButtonDown not called.
I want that if user not click on TextBlock then selection of item should not happen.
Hello I need a multicolumn control with variable heights and with expand/collapse capability. My approach so far is this-
<ListView Grid.Row="1" ItemsSource="{Binding MyCollection}" ScrollViewer.HorizontalScrollBarVisibility="Disabled" Grid.IsSharedSizeScope="True" VerticalContentAlignment="Center">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel></WrapPanel>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
<control:UCNewsFeed Margin="6" DataContext="{Binding Post}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
please notice that UCNewsFeed is a usercontrol which is given below-
<Grid x:Name="MainGrid">
<Grid.RowDefinitions>
<RowDefinition Height="57"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Grid x:Name="namePanel">
<StackPanel x:Name="nameContainer">
<TextBlock>Lamia Mehreen</TextBlock>
<TextBlock>Monday at 12:02pm</TextBlock>
<Button/>
</StackPanel>
</Grid>
<Border x:Name="hiddenPanel" Visibility="Collapsed" Grid.Row="1">
<StackPanel x:Name="editPanel" Orientation="Horizontal">
<RichTextBox/>
<Button Margin="0" Foreground="{x:Null}" Style="{DynamicResource ButtonStyle1}" BorderThickness="0" Background="{x:Null}" BorderBrush="{x:Null}" Focusable="False" HorizontalAlignment="Center" VerticalAlignment="Center" Padding="0" Width="37" Height="37"/>
</StackPanel>
</Border>
</Grid>
The layout is so far okay. The problem arises when "hiddenPanel"'s visibility is switched to visible from code behind. The entire row of the listview gets the height of the selected row.
I need to expand one cell only, NOT an entire row. Please suggest any approach that might come in handy. (I have simplified the XAML for easy reading, they might not look like the attached images)
I am trying to format the scroll view to completely occupy the parent container, but it looks like I'm missing something. Any suggestions would be great.
XAML:
<Border Grid.Row="0" BorderBrush="#1B5468" BorderThickness="3,3,3,3" CornerRadius="7,7,7,7" Margin="5,0,5,5">
<StackPanel Height="Auto" Width="Auto" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<StackPanel HorizontalAlignment="Center" Width="350" Height="30">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Image Source="../Images/Blue.png" Stretch="Fill" Margin="7,0,5,-27" Height="52" />
<TextBlock HorizontalAlignment="Center" Height="Auto" Margin="36,3,-2,4" Name="lblHeader" Text="Comments" VerticalAlignment="Center" Width="Auto" Foreground="Silver" FontWeight="Bold" FontSize="12" />
</Grid>
</StackPanel>
<ScrollViewer Height="Auto" HorizontalAlignment="Stretch" Name="dComments_Scroll" VerticalAlignment="Stretch" Width="Auto" HorizontalContentAlignment="Left" VerticalContentAlignment="Top">
<StackPanel Height="Auto" Name="dStack_Comments" Width="Auto" HorizontalAlignment="Left" VerticalAlignment="Top" UseLayoutRounding="False">
</StackPanel>
</ScrollViewer>
</StackPanel>
</Border>
By putting your ScrollViewer in a StackPanel, you're saying "make this ScrollViewer just tall enough to hold its content". That's what StackPanel is designed to do -- to make each child exactly as tall as it needs to be to show all its content, and then stack the next child right underneath. If that's not the layout you want, don't use a StackPanel.
Edit: Instead of a StackPanel inside your Border, you probably want a Grid. (I originally wrote DockPanel, forgetting that Silverlight doesn't ship with a DockPanel.) Grid is flexible enough to let you have some controls autosized, and other controls filling (or sharing) the remainder of the available space.
<Border ...>
<Grid ...>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" ...>
...
</StackPanel>
<ScrollViewer Grid.Row="1" ...>
...
</ScrollViewer>
</Grid>
</Border>
Also, once you get it working, I'd strongly suggest that you see if you can simplify your XAML. You're setting a lot of properties to their default values (e.g. HorizontalAlignment="Stretch", Height="Auto"), which just makes your XAML harder to read and maintain. If you can start to learn which attributes you can remove and still keep the same behavior, you'll have a much better handle on XAML development.