Add a MaterialDesign Expander - wpf

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>

Related

TextBox HideSelection in XAML

Is there any way to do the equivalent of TextBox.HideSelection=false in WPF?
The code below is as close as I can get it - where you need to "tab" through the fields to get them to show up.
I need the selections to at least all show when the button is pressed.
(My actual application is binding to selectionstart/length settings)
(also: any other control that allows range highlighting would be fine too!)
Thanks for any help!
<Window x:Class="selectionbrush.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"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Style TargetType="{x:Type TextBox}">
<Setter Property="IsInactiveSelectionHighlightEnabled" Value="True"/>
<Setter Property="IsReadOnly" Value="True"/>
<Setter Property="Margin" Value="5"/>
<Setter Property="SelectionBrush" Value="Green"/>
<Style.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelectionActive" Value="false"/>
</MultiTrigger.Conditions>
<Setter Property="SelectionBrush" Value="Red"/>
</MultiTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<StackPanel>
<Button Content="set selections" Click="Button_Click" Margin="5" MaxWidth="100" HorizontalAlignment="Left" Padding="5,0,5,0"/>
<TextBox x:Name="tb1" SelectionStart="1" SelectionLength="8" Text="Lorem ipsum dolor sit amet, agam dolore mediocritatem eu qui"/>
<TextBox x:Name="tb2" SelectionStart="5" SelectionLength="3" Text="Lorem ipsum dolor sit amet, agam dolore mediocritatem eu qui"/>
<TextBox x:Name="tb3" SelectionStart="9" SelectionLength="12" Text="Lorem ipsum dolor sit amet, agam dolore mediocritatem eu qui"/>
<TextBox x:Name="tb4" SelectionStart="4" SelectionLength="9" Text="Lorem ipsum dolor sit amet, agam dolore mediocritatem eu qui"/>
<TextBox x:Name="tb5" SelectionStart="11" SelectionLength="4" Text="Lorem ipsum dolor sit amet, agam dolore mediocritatem eu qui"/>
</StackPanel>
with this in the codebehind:
private void Button_Click(object sender, RoutedEventArgs e)
{
tb1.SelectionStart = 6; tb1.SelectionLength = 5;
tb2.SelectionStart = 17; tb2.SelectionLength = 7;
tb3.SelectionStart = 8; tb3.SelectionLength = 8;
tb4.SelectionStart = 12; tb4.SelectionLength = 3;
tb5.SelectionStart = 14; tb5.SelectionLength = 9;
}
It seems impossible with TextBox - I'm going to use a RichTextBox instead...
Private Sub TextBox_LostFocus(sender As Object, e As RoutedEventArgs)
e.Handled = True
'This keeps the selected text visible by setting handled equal to TRUE
End Sub

Fade in/out animation cause the ScrollViewer's content blurry

Here is my code, it can runs on Windows Phone 8 emulator.
XAML:
<Grid x:Name="ContentPanel">
<ScrollViewer>
<StackPanel>
<Button Content="Sample Content" Click="ButtonBase_OnClick">
<Button.Style>
<Style TargetType="Button">
<Setter Property="Width" Value="400"></Setter>
<Setter Property="Height" Value="100"></Setter>
<Setter Property="HorizontalContentAlignment" Value="Center"></Setter>
<Setter Property="VerticalContentAlignment" Value="Center"></Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<Border CornerRadius="10,10,10,10"
Background="{StaticResource PhoneAccentBrush}"
BorderBrush="#FF000000" BorderThickness="1,1,1,1"
x:Name="border" RenderTransformOrigin="0.5,0.5">
<Border.RenderTransform>
<TransformGroup>
<ScaleTransform />
<SkewTransform />
<RotateTransform />
<TranslateTransform />
</TransformGroup>
</Border.RenderTransform>
<ContentPresenter x:Name="contentPresenter"
ContentTemplate="{TemplateBinding ContentTemplate}"
VerticalAlignment="Center"
HorizontalAlignment="Center" />
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Button.Style>
</Button>
<TextBlock TextWrapping="Wrap">
Lorem ipsum Pariatur sint occaecat sunt sint do labore adipisicing
eiusmod incididunt culpa laborum consequat magna dolor labore sunt sed
ullamco anim adipisicing do pariatur ea esse qui sint magna in voluptate
Duis id ut anim id.
</TextBlock>
</StackPanel>
</ScrollViewer>
</Grid>
C#:
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
var storyb = new Storyboard();
Duration Show_Duration = new Duration(new TimeSpan(0, 0, 0, 0, 450));
DoubleAnimation m_OpacityAni = new DoubleAnimation();
m_OpacityAni.Duration = Show_Duration;
m_OpacityAni.From = 1.0;
m_OpacityAni.To = 0.0;
m_OpacityAni.AutoReverse = true;
storyb.Children.Add(m_OpacityAni);
Storyboard.SetTarget(m_OpacityAni, ContentPanel);
Storyboard.SetTargetProperty(m_OpacityAni, new PropertyPath("(UIElement.Opacity)"));
storyb.Begin();
}
Right now, because the height of content is smaller than the Grid named "ContentPanel", so when the animation begins, all contents will fade in/out without blurriness. But if I duplicate that TextBlock in order to make the ScrollViewer longer(make it scrollable), then run the animation again. Those contents will display blurry until it ends.
If I remove the ScrollViewer tag, all contents will display clear.
Although it won't cause some bad side effects, but I wanna know why it will display like this.
Look forward to your answers. Thanks!
Maybe it sets ScrollViewer.CacheMode = CacheMode.BitmapCache during the animation.

How do I make a WPF TextBlock show my text on multiple lines?

i have a wpf window where i have a stackpanel with two viewports in it - each Viewport with a textblock in it.
<Grid>
<StackPanel VerticalAlignment="Center" Orientation="Vertical" >
<Viewbox Margin="100,0,100,0">
<TextBlock x:Name="headerText"
Text="Lorem ipsum dolor"
Foreground="Black"/>
</Viewbox>
<Viewbox Margin="150,0,150,0">
<TextBlock x:Name="subHeaderText"
Text="Lorem ipsum dolor, Lorem ipsum dolor, lorem isum dolor, Lorem ipsum dolor, Lorem ipsum dolor, lorem isum dolor, "
TextWrapping="Wrap"
Foreground="Gray" />
</Viewbox>
</StackPanel>
</Grid>
What i would like to achieve is that the top textblock is the heading with a bigger text. The second textblock is the sub heading with a smaller text. No matter how much text there is for either the heading or the subheading the font should dynamic become smaller/bigger. My problem is that i would like the subheading to be fixed width. This means that, the font should be a percentage (70%) of the heading and wrap to multiple lines, depending on how much text i have. I enclosed the code I have thus far... im missing something with that subheading, cant figure out what. Cheers
Edit
Basically what i want achieve is that the sub header wraps the text so it can expand it downwards with the font being a 70% of the heading - no matter how big that font is.
Nesting a stackpanel will cause the textbox to wrap properly:
<Viewbox Margin="120,0,120,0">
<StackPanel Orientation="Vertical" Width="400">
<TextBlock x:Name="subHeaderText"
FontSize="20"
TextWrapping="Wrap"
Foreground="Black"
Text="Lorem ipsum dolor, lorem isum dolor,Lorem ipsum dolor sit amet, lorem ipsum dolor sit amet " />
</StackPanel>
</Viewbox>
Use the property TextWrapping of the TextBlock element:
<TextBlock Text="StackOverflow Forum"
Width="100"
TextWrapping="WrapWithOverflow"/>
Use Linebreak:
<TextBlock>
<Run Text="Line1"/>
<LineBreak/>
<Run Text="Line2" FontStyle="Italic" FontSize="9"/>
<LineBreak/>
<Run Text="Line3"/>
</TextBlock>
Refer this: https://social.msdn.microsoft.com/Forums/vstudio/en-US/51a3ffe4-ec82-404a-9a99-6672f2a6842b/how-to-give-multiline-in-textblock?forum=wpf
Thanks,
RDV
This gets part way there. There is no ActualFontSize property but there is an ActualHeight and that would relate to the FontSize. Right now this only sizes for the original render. I could not figure out how to register the Converter as resize event. Actually maybe need to register the FontSize as a resize event. Please don't mark me down for an incomplete answer. I could not put code sample in a comment.
<Window.Resources>
<local:WidthConverter x:Key="widthConverter"/>
</Window.Resources>
<Grid>
<Grid>
<StackPanel VerticalAlignment="Center" Orientation="Vertical" >
<Viewbox Margin="100,0,100,0">
<TextBlock x:Name="headerText" Text="Lorem ipsum dolor" Foreground="Black"/>
</Viewbox>
<TextBlock Margin="150,0,150,0" FontSize="{Binding ElementName=headerText, Path=ActualHeight, Converter={StaticResource widthConverter}}" x:Name="subHeaderText" Text="Lorem ipsum dolor, Lorem ipsum dolor, lorem isum dolor, Lorem ipsum dolor, Lorem ipsum dolor, lorem isum dolor, " TextWrapping="Wrap" Foreground="Gray" />
</StackPanel>
</Grid>
</Grid>
Converter
[ValueConversion(typeof(double), typeof(double))]
public class WidthConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
double width = (double)value*.7;
return width; // columnsCount;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
If you just want to have your header font a little bit bigger then the rest, you can use ScaleTransform. so you do not depend on the real fontsize.
<TextBlock x:Name="headerText" Text="Lorem ipsum dolor">
<TextBlock.LayoutTransform>
<ScaleTransform ScaleX="1.1" ScaleY="1.1" />
</TextBlock.LayoutTransform>
</TextBlock>
All the answers above did not satisfy my need and I am pretty sure most here will have a similar problem.
What i wanted was to bind a string property which contains linefeeds to a textblock and have it display in multible lines rather than in a single line.
WPF does not seem to have an easy solution for this so i found my own little workaround. I use a textbox with a custom style that will disable its editability and makes it look like a Textblock. Works like a charm with the added benefit that people can now copy the text from your textblock, which atleast in all my application is a win!
<Style TargetType="{x:Type TextBox}" x:Key="TextBlock">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Foreground" Value="Black"/>
<Setter Property="IsReadOnly" Value="True"/>
<Setter Property="FontSize" Value="12"/>
<Setter Property="VerticalContentAlignment" Value="Left"/>
</Style>
It can be used like this:
<TextBox Style="{StaticResource TextBlock}" Text="{Binding UpdateChanglog}"/>
and will look like this:
Text bound was:
•Update is from server!
•The camera now actually works
•Images are sharp
•Network is great
•Everybody happy

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