Bind Content of a UserControl to a Popup inside that UserControl - wpf

I am trying to create a UserControl consisting of a button that causes an info popup to show up when clicked. The design and style of the button is defined in the UserControl and will not change, the Content of the Popup should use the Content property of the UserControl itself.
My current approach for the control is:
<UserControl x:Class="InfoPopup"
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="30" d:DesignWidth="30">
<UserControl.Template>
<ControlTemplate TargetType="UserControl">
<Grid>
<ToggleButton Name="button">
<Label Content="i"/>
</ToggleButton>
<Popup IsOpen="{Binding IsChecked, ElementName=button}" StaysOpen="False">
<ContentPresenter />
</Popup>
</Grid>
</ControlTemplate>
</UserControl.Template>
</UserControl>
And the code where it is used should look like this:
<local:InfoPopup VerticalAlignment="Top" HorizontalAlignment="Right" Height="30" Width="30">
<TextBlock TextWrapping="Wrap" Margin="5" MaxWidth="400">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Cras pulvinar mattis nunc sed. Interdum consectetur libero id faucibus nisl tincidunt eget nullam. Vestibulum rhoncus est pellentesque elit ullamcorper. Enim blandit volutpat maecenas volutpat blandit aliquam etiam erat velit.
<LineBreak />
<LineBreak />
Est sit amet facilisis magna. Quis enim lobortis scelerisque fermentum dui faucibus. Magna eget est lorem ipsum dolor sit amet. Aenean pharetra magna ac placerat vestibulum lectus mauris ultrices. Viverra nam libero justo laoreet sit amet cursus sit. Fermentum posuere urna nec tincidunt praesent. Maecenas volutpat blandit aliquam etiam erat velit scelerisque.
</TextBlock>
</local:InfoPopup>
This causes the popup to show up with the correct size (according to the specified Content) when the button is clicked, but the actual popup content is just (literally) a black box.
What am I missing? I am not very familiar with WPF bindings and templates.

The popup contents are black because the foreground and background are black (by default).
You can either set AllowsTransparency="True" on the Popup (if you want the background to be transparent).
<Popup IsOpen="{Binding IsChecked, ElementName=button}" StaysOpen="False" AllowsTransparency="True">
Or, do something like put a Grid around the ContentPresenter with a background of your choice, like this:
<Grid Background="White">
<ContentPresenter />
</Grid>
If you want the default background color, try this:
<Grid Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}">
<ContentPresenter />
</Grid>

Related

Add a MaterialDesign Expander

I want to add an Expander to my project with MaterialDesign. While adding, I encounter the following errors.
How can I access the style resources in TextBlocks?
<Grid>
<materialDesign:Card>
<StackPanel>
<Expander HorizontalAlignment="Stretch" Header="Expander Example 2a">
<StackPanel Orientation="Vertical" TextBlock.Foreground="{DynamicResource MaterialDesignBody}" Margin="24,8,24,16">
<TextBlock Text="Your Content" />
<TextBlock Style="{StaticResource HorizontalExpanderContentTextBlock}" />
</StackPanel>
</Expander>
<Border Style="{StaticResource HorizontalDividerBorder}" />
<Expander HorizontalAlignment="Stretch" Header="Expander Example 2b">
<StackPanel Orientation="Vertical" TextBlock.Foreground="{DynamicResource MaterialDesignBody}" Margin="24,8,24,16">
<TextBlock Text="Your Content" />
<TextBlock Style="{StaticResource HorizontalExpanderContentTextBlock}" />
</StackPanel>
</Expander>
<Border Style="{StaticResource HorizontalDividerBorder}" />
<Expander HorizontalAlignment="Stretch" Header="Expander Example 2c">
<StackPanel Orientation="Vertical" TextBlock.Foreground="{DynamicResource MaterialDesignBody}" Margin="24,8,24,16">
<TextBlock Text="Your Content" />
<TextBlock Style="{StaticResource HorizontalExpanderContentTextBlock}" />
</StackPanel>
</Expander>
</StackPanel>
</materialDesign:Card>
</Grid>
Errors:
Error The resource "HorizontalDividerBorder" could not be resolved.
Error The resource "HorizontalExpanderContentTextBlock" could not be resolved.
Error The resource "HorizontalDividerBorder" could not be resolved.
Error The resource "HorizontalExpanderContentTextBlock" could not be resolved.
Error The resource "HorizontalExpanderContentTextBlock" could not be resolved.
App.xaml Code:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Light.xaml" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Defaults.xaml" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Primary/MaterialDesignColor.DeepPurple.xaml" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Accent/MaterialDesignColor.Lime.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
The HorizontalDividerBorder and HorizontalExpanderContentTextBlock styles are not shipped with the Material Design library, they are local styles in their WPF demo application.
The styles are defined in MaterialDesignInXamlToolkit/MainDemo.Wpf/Expander.xaml. If you want to use them, just copy them over into a local resource dictionary in your project.
Example
Create a new resource dictionary MaterialDesignWpfDemoStyles.xaml directly in your project and copy over the styles from the link above. It should look like this:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApp1">
<Style TargetType="{x:Type TextBlock}" x:Key="HorizontalExpanderContentTextBlock">
<Setter Property="Opacity" Value=".68"/>
<Setter Property="Text" Value="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."/>
<Setter Property="TextWrapping" Value="Wrap"/>
</Style>
<Style TargetType="{x:Type Border}" x:Key="HorizontalDividerBorder">
<Setter Property="Background" Value="{DynamicResource MaterialDesignDivider}"/>
<Setter Property="UseLayoutRounding" Value="True"/>
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="Height" Value="1"/>
</Style>
</ResourceDictionary>
Add the resource dictionary after your other dictionaries in App.xaml:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Light.xaml" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Defaults.xaml" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Primary/MaterialDesignColor.DeepPurple.xaml" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Accent/MaterialDesignColor.Lime.xaml" />
<ResourceDictionary Source="MaterialDesignWpfDemoStyles.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>

Set Grid Column width between 2 enums in Semantic UI React

I am building a ui using Semantic UI React library and want to set a column width between 3 and 4. I am using 3.5 and 0.5 but since the library enums do not support it, the design is not rendering properly. All the column widths add up to 16.
This is how the UI is rendering
This is how I want it to be. Mobile width: 3.5, spacer: 0.5, text: 3, spacer: 1 and so on
<Grid.Row>
<Grid.Column width={1} />
<Grid.Column width={3.5}>
<Image src={mobileQuizPrevious} />
</Grid.Column>
<Grid.Column width={0.5} />
<Grid.Column width={3}>
<p>
<strong>Before</strong>
<br />
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras
augue nulla, condimentum a tortor non, gestas maximus neque.
</p>
</Grid.Column>
<Grid.Column width={1} />
<Grid.Column width={3.5}>
<Image src={mobileQuizNew} />
</Grid.Column>
<Grid.Column width={0.5} />
<Grid.Column width={3}>
<p>
<strong>After</strong>
<br />
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras
augue nulla, condimentum a tortor non, gestas maximus neque.
</p>
</Grid.Column>
</Grid.Row>
Semantic UI grid width options
Any help would be appreciated!
I solved it like this. Came quite close to the intended design
<Grid.Row centered>
<Grid.Column width={1} />
<Grid.Column width={3} style={{ marginRight: "1em" }}>
<Image src={image1} />
</Grid.Column>
<Grid.Column width={3}>
<p>
<strong>Before</strong>
<br />
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras
augue nulla, condimentum a tortor non, gestas maximus neque.
</p>
</Grid.Column>
<Grid.Column width={1} />
<Grid.Column width={3} style={{ marginRight: "1em" }}>
<Image src={image2} />
</Grid.Column>
<Grid.Column width={3}>
<p>
<strong>After</strong>
<br />
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras
augue nulla, condimentum a tortor non, gestas maximus neque.
</p>
</Grid.Column>
</Grid.Row>

Blurry image animation

On application startup, I'd like to do a small animation: a logo should transform from large and blurry to normal and clear. This is what I have so far:
<Grid>
<Border>
<Image Height="250" Name="AnimationLogo" Source="Logo.png">
</Image>
</Border>
<Grid.Triggers>
<EventTrigger RoutedEvent="Window.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Height" Storyboard.TargetName="AnimationLogo">
<LinearDoubleKeyFrame Value="50" KeyTime="0:0:5.0"></LinearDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Grid.Triggers>
I know that I can animate a static blurry like this:
<Image.Effect>
<BlurEffect Radius="20"/>
</Image.Effect>
But I could not manage to animate this BlurEffect on the image. There is no Property "Radius" on the image that I could use in the animation.
I'd be thankful for a hint or a good link!
You can try naming the BlurEffect
<Image.Effect>
<BlurEffect Radius="20" x:Name="blurEffect"/>
</Image.Effect>
And animation for TargetName blurEffect
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Radius"
Storyboard.TargetName="blurEffect">
<LinearDoubleKeyFrame Value="50" KeyTime="0:0:5.0"></LinearDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
It is possible to Animate Blur on Loaded event usig the WPF Transitionz library.
A simple code example:
<Window x:Class="WpfApplication15.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:tz="http://schemas.abtsoftware.co.uk/transitionz"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525"
WindowStartupLocation="CenterScreen">
<Grid>
<TextBlock Foreground="#AAA" Margin="10" TextWrapping="Wrap" Text="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer nec odio. Praesent libero. Sed cursus ante dapibus diam. Sed nisi. Nulla quis sem at nibh elementum imperdiet. Duis sagittis ipsum. Praesent mauris. Fusce nec tellus sed augue semper porta. Mauris massa. Vestibulum lacinia arcu eget nulla. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur sodales ligula in libero. Sed dignissim lacinia nunc. Curabitur tortor. Pellentesque nibh. Aenean quam. In scelerisque sem at dolor. Maecenas mattis. Sed convallis tristique sem. Proin ut ligula vel nunc egestas porttitor. Morbi lectus risus, iaculis vel, suscipit quis, luctus non, massa. Fusce ac turpis quis ligula lacinia aliquet. Mauris ipsum. Nulla metus metus, ullamcorper vel, tincidunt sed, euismod in, nibh. Quisque volutpat condimentum velit. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Nam nec ante. Sed lacinia, urna non tincidunt mattis, tortor neque adipiscing diam, a cursus ipsum ante quis turpis. Nulla facilisi. Ut fringilla. Suspendisse potenti. Nunc feugiat mi a tellus consequat imperdiet. Vestibulum sapien. Proin quam. Etiam ultrices. Suspendisse in justo eu magna luctus suscipit. Sed lectus. Integer euismod lacus luctus magna. Quisque cursus, metus vitae pharetra auctor, sem massa mattis sem, at interdum magna augue eget diam. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Morbi lacinia molestie dui. Praesent blandit dolor. Sed non quam. In vel mi sit amet augue congue elementum. Morbi in ipsum sit amet pede facilisis laoreet. Donec lacus nunc, viverra nec, blandit vel, egestas et, augue. Vestibulum tincidunt malesuada tellus. Ut ultrices ultrices enim. Curabitur sit amet mauris. Morbi in dui quis est pulvinar ullamcorper. "
tz:Transitionz.Opacity="{tz:OpacityParams Duration=2000, From=0, To=1, TransitionOn=Loaded}"
tz:Transitionz.Blur="{tz:BlurParams Duration=2000, From=20, To=0, TransitionOn=Loaded}"/>
</Grid>
</Window>
Which results in this animation on loaded of the window.
It is also possible to animate blur on property changed by binding the tz:Transitions.Blur to a Property of type BlurParams in the ViewModel.

WPF: How do I access the rendered dimensions of a Path in XAML?

I am trying to overlay text content on top of a region described by a Path. The Path is in a ViewBox wrapped Canvas so that it can scale to any size. The TextBlock is in a Canvas wrapped Grid that is trying to use the Path dimensions to determine the placement of the text block.
<?xml version="1.0" encoding="UTF-8"?>
<Canvas
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"
mc:Ignorable="d" Width="1299" Height="413">
<ContentControl Width="300" Height="Auto">
<Grid>
<Viewbox Stretch="Uniform" x:Name="MyViewBox">
<Canvas Width="121.664" Height="79.158" x:Name="MyCanvas">
<Canvas.LayoutTransform>
<TransformGroup>
<ScaleTransform ScaleX="1" ScaleY="1"/>
</TransformGroup>
</Canvas.LayoutTransform>
<Path x:Name="MyPath" Width="115.666" Height="54.334" Canvas.Left="2.998" Canvas.Top="3.086" Data="M 115.666015,46.333496 C 115.666015,50.733887 112.066406,54.333985 107.666015,54.333985 L 7.99999999999994,54.333985 C 3.59960900000004,54.333985 0,50.733887 0,46.333496 L 0,8 C 0,3.60058600000002 3.59960900000004,0 7.99999999999994,0 L 107.666015,0 C 112.066406,0 115.666015,3.60058600000002 115.666015,8 L 115.666015,46.333496 Z">
<Path.Fill>
<SolidColorBrush Color="Red"/>
</Path.Fill>
</Path>
</Canvas>
</Viewbox>
<Canvas>
<Grid Width="115.666" Height="54.334" Canvas.Left="2.998" Canvas.Top="3.086" Margin="10,10">
<Thumb/>
<TextBlock TextWrapping="Wrap">
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</TextBlock>
</Grid>
</Canvas>
</Grid>
</ContentControl>
</Canvas>
Two problems arise. First, the Grid is using the declared dimensions of the Path, not the final rendered dimensions. Also, if I set the ScaleTransform.ScaleY to "-1" on my Path Canvas (to mirror the path vertically), the TextBlock does not relocate to the new positions of my Path.
Is it possible to do this in XAML, or will I have to use code-behind to read the location at runtime?
EDIT: The example Grid is not actually referencing the Path properties, as I was unable to figure out the right properties to reference.
You can bind to the Path's ActualWidth and ActualHeight like below:
"{Binding ElementName=MyPath, Path=ActualHeight}"
HTH

How do I reference the Toggle Button Circle and override vertical alignment of the Aero theme Expander?

Currently, I am referencing the Aero theme in my App.xml file.
In the main.xml file, I am using expanders to display the content in a resizable width app.
(For this example, I limited the width to 500)
The expander header content generally will be short, but it allows for up to 500 chars.
Depending on the window size (600 pixels by default), the content can wrap (thereby stretching the expander header downwards).
This is fine, but the toggle button (a circle /w arrow) is set for VerticalAlignment=center from what I can tell.
I need a way to override that VerticalAlignment in a style without re-creating the Aero template for the Expander.
I just cant seem to reference the circle and arrow objects.
I have tried overriding Toggle Button as well, with no luck.
As you can see below, I can override some aspects of the Aero Expander.
I just need that little nudge to get the Toggle Button Circle and Arrow objects to change the VerticalAlignment.
Thanks
Code example follows:
<Window.Resources>
<Style TargetType="{x:Type Expander}" BasedOn="{StaticResource {x:Type Expander}}">
<Setter Property="Foreground" Value="White" />
<Setter Property="Background" Value="#464646" />
<Setter Property="Width" Value="Auto" />
<Setter Property="Margin" Value="1,0,1,0" />
<Setter Property="IsExpanded" Value="False" />
</Style>
</Window.Resources>
<Expander ContextMenu="{StaticResource cMnu}" Width="auto">
<Expander.Header>
<StackPanel Orientation="Horizontal" Width="auto" Margin="0">
<TextBlock Width="65">Normal</TextBlock>
<TextBlock Width="80">Open</TextBlock>
<TextBlock Width="80">10/31/2009</TextBlock>
<TextBlock TextWrapping="Wrap" Width="500">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Aliquam ultrices auctor magna, sit amet commodo ipsum accumsan eu.
Sed a mollis felis. Nam ullamcorper augue vel mauris consequat imperdiet.
Nunc in augue mauris.
Quisque metus tortor, porttitor nec auctor id, mollis nec ipsum.
Suspendisse eget ipsum vitae lectus fermentum porta.
Aliquam erat volutpat.
Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.
Phasellus congue dui ac arcu eleifend a amet.
</TextBlock>
</StackPanel>
</Expander.Header>
</Expander>
If you look at the default template for the Expander, you can see why none of your property setters are working:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ToggleButton IsChecked="{Binding Path=IsExpanded,Mode=TwoWay,
RelativeSource={RelativeSource TemplatedParent}}"
OverridesDefaultStyle="True"
Template="{StaticResource ExpanderToggleButton}"
Background="{StaticResource NormalBrush}" />
<ContentPresenter Grid.Column="1"
Margin="4"
ContentSource="Header"
RecognizesAccessKey="True" />
</Grid>
The ToggleButton's VerticalAlignment is what you are after, and there are no setters for it.
It seems to me that there is no way to change this alignment property through the Style. You must provide a new template.

Resources