i tried do some content in FlowDocument to be highlighten by rectangle. like following code:
<FlowDocument>
<Paragraph>
<Span>
here is a span.
<Span.Background>
<VisualBrush>
<VisualBrush.Visual>
<Rectangle Fill="Gray" RadiusX="5" RadiusY="5" Width="100" Height="50"/>
</VisualBrush.Visual>
</VisualBrush>
</Span.Background>
</Span>
</Paragraph>
<FlowDocument>
i want to set rectangle's width and height to span.
how can i get span's actual width and height which determined by span's content's length?
added:
it dosen't work. (it occured System.InvalidOperationException in design time)
<FlowDocument>
<Paragraph>
<Span>
Here is a span.
<Span.Background>
<VisualBrush>
<VisualBrush.Visual>
<Rectangle Fill="Gray" RadiusX="5" RadiusY="5" Height="50" Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Span}}, Path=Width}"/>
</VisualBrush.Visual>
</VisualBrush>
</Span.Background>
</Span>
</Paragraph>
</FlowDocument>
Try something like this
Width="{Binding RelativeSource=
{RelativeSource FindAncestor,
AncestorType={x:Type Span}},
Path=ActualWidth}"
>
A converter can be usefull on this binding for proportions, tell me if you need a converter example also.
Related
I am completely new to WPF, so please be gentle. :) I have a 4x4 grid. Within each cell, I want to have concentric rectangles that frame the cell and then place widgets within them. The outer rectangle is to fill the cell. The inner rectangles are then to be within the boundaries of the outer rectangles, etc. I am able to place the first rectangle successfully. However, I am having a devil of a time placing the inner rectangles. My gut says this should be doable without code-behind.
I've tried a canvas within a canvas, not to mention various permutations and combinations.
<Grid Grid.Row="0" Grid.Column="0" >
<Canvas>
<Rectangle Canvas.Left="0" Stroke="Gray" Canvas.Top="0" RadiusX="10" RadiusY="10" StrokeThickness="20" x:Name="r0c0"
Stretch="Fill" Width="{Binding ActualWidth, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Grid}}}"
Height="{Binding ActualHeight, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Grid}}}"/>
<Rectangle Canvas.Left="15" Stroke="Blue" Canvas.Top="15" RadiusX="5" RadiusY="5" StrokeThickness="10"
Stretch="Fill" Width="{Binding ActualWidth, ElementName=r0c0}"
Height="{Binding ActualHeight, ElementName=r0c0}"/>
</Canvas>
</Grid>
Figured it out. Canvas and rectangle was overdoing it. Borders were the route to go.
<Grid Grid.Row="0" Grid.Column="1">
<Border BorderThickness="20" BorderBrush="Gray" CornerRadius="10"
Margin="0,0,0,0"/>
<Border BorderThickness="10" BorderBrush="Blue" CornerRadius="10"
Margin="15,15,15,15"/>
</Grid>
(I'm extremely new to xaml)
<Canvas Width="200" Height="100">
<Rectangle Width="" Height=""></Rectangle>
</Canvas>
Now, is it possible to set Rectangle's Width and Height the same as Canvas's using Xaml only?
or is necessary to use code?
You should make Data Binding. Looks like this:
<Canvas Name="myCanvas" Width="200" Height="100">
<Rectangle Width="{Binding ElementName=myCanvas, Path=Width}" Height="{Binding ElementName=myCanvas, Path=Height}"> </Rectangle>
</Canvas>
So I'm adding my views directly to the TabControl's Items collection at runtime (instead of creating TabItems around them and addings those TabItems to TabControl). The views expose a property (wrapper around a ViewModel property of the same name) named HasChanges that I want to bind to TabItem's Header to show a Asterisk (*) sign to identify tabs with unsaved changes, just like VS does. I have already tried using DataTemplates but am having trouble accessing the view object in the DataTemplate. What's the correct way of doing this? Here's one of my several attempts:
<TabControl.ItemTemplate>
<DataTemplate DataType="UserControl">
<StackPanel Orientation="Horizontal" Margin="0" Height="22">
<TextBlock VerticalAlignment="Center" Text="{Binding HeaderText, RelativeSource={RelativeSource AncestorType=UserControl}}" />
<TextBlock Text="*" Visibility="{Binding HasChanges, RelativeSource={RelativeSource Mode=TemplatedParent}, Converter={StaticResource B2VConverter}}" />
</StackPanel>
</DataTemplate>
</TabControl.ItemTemplate>
Note that I'm trying two different binding methods for the two TextBlocks, none of which is working. My views inherit from UserControl and expose properties HasChanges and HeaderText.
OK. I solved it myself. For anyone else trying to implement a VS-like Close button and unsaved changes asterisk, here's the template:
<TabControl.ItemContainerStyle>
<Style TargetType="{x:Type TabItem}">
<Setter Property="HeaderTemplate" >
<Setter.Value>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="0" Height="22">
<TextBlock VerticalAlignment="Center" Text="{Binding RelativeSource={RelativeSource AncestorType=TabItem}, Path=Content.HeaderText}" />
<TextBlock Text=" *" ToolTip="Has unsaved changes" Visibility="{Binding Content.DataContext.HasChanges, RelativeSource={RelativeSource AncestorType=TabItem}, Converter={StaticResource B2VConverter}}" />
<Button Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}" Width="18" Height="18"
Margin="6,0,0,0" Padding="0" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" HorizontalAlignment="Center"
Command="{Binding DataContext.TabClosingCommand, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=UserControl}}"
VerticalAlignment="Center" Focusable="False">
<Grid Margin="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Line StrokeThickness="3" StrokeStartLineCap="Round" StrokeEndLineCap="Round" Stroke="Gray" X1="1" Y1="1" X2="9" Y2="9" HorizontalAlignment="Center" VerticalAlignment="Center" />
<Line StrokeThickness="3" StrokeStartLineCap="Round" StrokeEndLineCap="Round" Stroke="Gray" X1="1" Y1="9" X2="9" Y2="1" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
</Button>
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</TabControl.ItemContainerStyle>
Results in an elegant drawing-based button with a flat-look. Your View must implement Boolean HasChanges and HeaderText properties, plus you need to define a BooleanToVisibilityConverter in your resources section, named B2VConverter.
I have a TextBox defined as this:
<TextBox>
<TextBox.Background>
<VisualBrush>
<VisualBrush.Visual>
<StackPanel>
<TextBlock Background="Blue" Opacity="0.5" Text="155"/>
</StackPanel>
</VisualBrush.Visual>
</VisualBrush>
</TextBox.Background>
</TextBox>
It looks like this:
However, when I remove the Background property, the text stretches like this:
Is there any way to add the background without changing the way the text looks?
If you use Background="Transparent" it will use the same layout but with no background color. Is that what you're trying to do?
a workarround of this problem which i don't know why it occurs would be to remove Background property from textblock and put it behind it like this
<Grid>
<Rectangle Fill="Blue"/>
<TextBox Height="100">
<TextBox.Background>
<VisualBrush Stretch="Fill" TileMode="None" AlignmentX="Left" AlignmentY="Top">
<VisualBrush.Visual>
<StackPanel>
<TextBlock Margin="0" Padding="0" Opacity="0.5" Text="155"/>
</StackPanel>
</VisualBrush.Visual>
</VisualBrush>
</TextBox.Background>
</TextBox>
</Grid>
I need to "decorate" a textBlock with a custom background (say, when IsSelected)
Actually I have two separate elements textBlock and its background rectangle:
<TextBlock x:Name="StopText" Text="Eiffel Tower"
Canvas.Left="17"
FontSize="14"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
FontFamily="Giddyup Std"
Canvas.Top="-16"
Padding="5">
</TextBlock>
<Rectangle x:Name="ShadowRectangle"
Fill="SkyBlue"
Canvas.Left="18"
Width="{Binding ElementName=StopText, Path=ActualWidth}"
Height="{Binding ElementName=StopText, Path=ActualHeight}"
RadiusX="5" RadiusY="5" Opacity="0.2" Canvas.Top="-17"
LayoutTransform="{Binding ElementName=StopText, Path=LayoutTransform}"/>
Now, when I want to Hide the textBlock I need to hide the rectangle too, etc. I think there is should be a more elegant way to do it.
Any remarks appreciated.
EDIT
Border approach
<Border x:Name="ShadowRectangle"
Background="Transparent"
Canvas.Left="18"
Canvas.Top="-17"
CornerRadius="5"
Opacity="0.2"
LayoutTransform="{Binding ElementName=StopText,
Path=LayoutTransform}">
<TextBlock x:Name="StopText" Text="Eiffel Tower"
FontSize="14" VerticalAlignment="Stretch"
HorizontalAlignment="Stretch" FontFamily="Giddyup Std"
Canvas.Top="-16" Padding="5">
</TextBlock>
</Border>
In a solution similar to your border approach, if you want no dependencies between the opacity of the border and the textblock, you could go with something like this:
<grid>
<rectangle />
<textblock />
<grid>
this should put the textblock over the rectangle since they are on the same grid cell.
They you only have to change the Rectangle.Fill when it's selected. You could do that using a DataTrigger on the Rectangle style.
You can make a Custom Control instead.
Here is a link for some ideers:
http://www.codeguru.com/cpp/i-n/internet/xml/article.php/c12521
Bind the visibility property for both the textblock and Rectangle to a bool in your viewmodel and use the BoolToVisibilityConverter to convert the bool value to a visibility value. Your XAML will look something like this:
<TextBlock x:Name="StopText" Text="Eiffel Tower"
Canvas.Left="17"
FontSize="14"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
FontFamily="Giddyup Std"
Canvas.Top="-16"
Padding="5"
Visibility="{Binding IsVis, Converter={StaticResource BooleanToVisibilityConverter}}">
</TextBlock>
<Rectangle x:Name="ShadowRectangle"
Fill="SkyBlue"
Canvas.Left="18"
Width="{Binding ElementName=StopText, Path=ActualWidth}"
Height="{Binding ElementName=StopText, Path=ActualHeight}"
RadiusX="5" RadiusY="5" Opacity="0.2" Canvas.Top="-17"
Visibility="{Binding IsVis, Converter={StaticResource BooleanToVisibilityConverter}}"/>
Using either the Border or Rectangle approach, you should be able to bind the Visibility of the decorator (Border or Rectangle) to the Visibility of the TextBlock.
<TextBlock x:Name="StopText" Text="Eiffel Tower"
Canvas.Left="17"
FontSize="14"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
FontFamily="Giddyup Std"
Canvas.Top="-16"
Padding="5">
</TextBlock>
<Rectangle x:Name="ShadowRectangle"
Fill="Red"
Canvas.Left="18"
Width="{Binding ElementName=StopText, Path=ActualWidth}"
Height="{Binding ElementName=StopText, Path=ActualHeight}"
RadiusX="5" RadiusY="5" Opacity="0.2" Canvas.Top="-17"
LayoutTransform="{Binding ElementName=StopText, Path=LayoutTransform}"
Visibility="{Binding ElementName=StopText}"/>
Let me suggest to use templated label (textblock wont accept templates and took more characters to type -). For your convenience, I wrapped it in a style:
<Window x:Class="_4203457.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Style TargetType="{x:Type Label}">
<Setter Property="FontSize" Value="14"/>
<Setter Property="FontFamily" Value="Giddyup Std"/>
<Setter Property="Padding" Value="5"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Label}">
<Grid>
<TextBlock Text="{TemplateBinding Content}"
FontSize="14"
Padding="5"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
FontFamily="Giddyup Std"
/>
<Rectangle x:Name="ShadowRectangle"
Fill="SkyBlue"
RadiusX="5" RadiusY="5" Opacity="0.5"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid Height="27" Width="454">
<Label Content="Eiffel Tower"/>
</Grid>