How do I change RichTextBox paragraph spacing? - wpf

I am using a RichTextBox in WPF, and am trying to set the default paragraph spacing to 0 (so that there is no paragraph spacing). While I could do this in XAML, I would like to achieve it programmatically if possible. Any ideas?

I did it with style (pun indented)
<RichTextBox Margin="0,51,0,0" Name="mainTextBox" >
<RichTextBox.Resources>
<Style TargetType="{x:Type Paragraph}">
<Setter Property="Margin" Value="0"/>
</Style>
</RichTextBox.Resources>
</RichTextBox>

Using Line Height
RichTextBox rtb = new RichTextBox();
Paragraph p = rtb.Document.Blocks.FirstBlock as Paragraph;
p.LineHeight = 10;

Close, so you got the points. Actually it turned out to be setting the margin,
p.Margin = new Thickness(0);

For me on VS2017 in WPF works this:
<RichTextBox HorizontalAlignment="Left" Height="126" Margin="10,280,0,0" VerticalAlignment="Top" Width="343" FontSize="14" Block.LineHeight="2"/>
The key is Block.LineHeight="2"
You can found this also in Properties view but you can't change below 6px from there.

RichTextBox rtb = new RichTextBox();
rtb.SetValue(Paragraph.LineHeightProperty, 1.0);

In C# 2008 WAP
richtextbox1.SelectionCharOffset =
-1 * ( Convert.ToInt32(R223.Txt_Space_Before.Text) * 100);
or
richtextbox1.SelectionCharOffset =
Convert.ToInt32(R223.Txt_Space_Before.Text) * 100;
can be used for Line Spacing.
This is the only way you can have line height spacing.

<RichTextBox Height="250" Width="500" VerticalScrollBarVisibility="Auto" TextWrapping="Wrap" IsReadOnly="True" >
<Paragraph>
XYZ
<LineBreak />
</Paragraph>
</RichTextBox>

I know this question was posted before I even started coding but I found that simply setting ShowSelectedMargin to true did the trick

Related

Path.Data styling works only on first instance of styled object

A have a ListBox of items, every ListBoxItem contains an icon in the form of a Path object, like so:
<ListBox.ItemTemplate>
<DataTemplate>
<Grid ...>
...
<Path Margin="4" Style="{StaticResource ErrorIconPath}"
Stretch="Uniform" Width="26" Height="26"
RenderTransformOrigin="0.5,0.5" Grid.Column="1" Grid.Row="1"
UseLayoutRounding="False"
HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
The Path's style is contained in Appl.xaml (Application.Resources section) and is the following:
<Style x:Key="ErrorIconPath" TargetType="Path">
<Setter Property="Data" Value="F1M874.094,289.369L854.3,254.63C854.028,254.151 853.515,253.856 852.958,253.856 852.403,253.856 851.89,254.151 851.617,254.63L831.824,289.369C831.555,289.84 831.559,290.416 831.835,290.883 832.111,291.348 832.618,291.634 833.165,291.634L872.752,291.634C873.299,291.634 873.805,291.348 874.081,290.883 874.357,290.416 874.361,289.84 874.094,289.369 M855.653,287.189L850.264,287.189 850.264,282.745 855.653,282.745 855.653,287.189z M855.653,279.41L850.264,279.41 850.264,266.077 855.653,266.077 855.653,279.41z" />
</Style>
The trouble is that only the first item in the ListBox binds the Data property as expected, the other ones don't bind it at all (hence they appear as blank space, but match the size of the Path). Also when I use the style anywhere else (i.e. outside the ListBox), only the first instance that occurs will bind.
The weird thing is that if I define for example the Fill property in the Style instead of inline, it works just fine and doesn't exibit the same problems as the Path property.
My guess is that is has something to do with Data not being a primitive type, but I haven't found any fixes.
EDIT: Interestingly, when I bind the Data property directly to System.String resource, it works. I would still like to be able to define this property via a Style though.
EDIT 2: I've just came across the same issue in WPF, when setting Path to a Content of a Button via a Style that is used across more buttons. The path shows up in just one buttons, the others are blank.
Path.Fill is a DependencyProperty, while Path.Data isn't. Instead do:
<DataTemplate>
<Grid ...>
...
<ContentPresenter Content="{StaticResource MyPath}"/>
</Grid>
</DataTemplate>
ContentPresenter.Content is a DependencyProperty so this should work:
<Path x:Key="MyPath" Margin="4" Style="{StaticResource ErrorIconPath}"
Stretch="Uniform" Width="26" Height="26" VerticalAlignment="Center"
RenderTransformOrigin="0.5,0.5" Grid.Column="1" Grid.Row="1"
UseLayoutRounding="False" HorizontalAlignment="Center"
Data="F1M874.094,289.369L854.3,254.63C854.028,254.151 853.515,253.856 852.958,253.856 852.403,253.856 851.89,254.151 851.617,254.63L831.824,289.369C831.555,289.84 831.559,290.416 831.835,290.883 832.111,291.348 832.618,291.634 833.165,291.634L872.752,291.634C873.299,291.634 873.805,291.348 874.081,290.883 874.357,290.416 874.361,289.84 874.094,289.369 M855.653,287.189L850.264,287.189 850.264,282.745 855.653,282.745 855.653,287.189z M855.653,279.41L850.264,279.41 850.264,266.077 855.653,266.077 855.653,279.41z"/>
I am guessing that Geometry cannot be shared. Have you tried setting the x:Shared= "false" to:
<Style x:Key="ErrorIconPath" TargetType="Path">
I've experienced the same behavior in Silverlight and asked a similar question here on StackOverflow.com
( https://stackoverflow.com/q/13426198/1796930), but as I'm writing this, it's been 1 month and I've yet to get even a single answer.
However, as you mentioned in your first edit, I too was able to perform a workaround by creating a resource with my geometry data as a string and then binding the Data property of the Path objects to the string resource resource.
I also had to create two instances of the Path objects that were identical other than each one using a different resource (i.e. two different icons) and then binding the visibility of each to a property in my ViewModel to display the appropriate one.
I am very sure that you did not forgot the stroke here in Path style
<Setter Property="Stroke" Value="Red"/>
I have tested you code on my machine , it worked fine if above line added in style
My first tought was your Path would be broken or not valid. But then I saw you are using the Syncfusion Metro Studio. I tried it with exactly the same code you have and it worked very well. In a Data Template of 5 Items or as a single Path Item.
Have you tried to set the Fill statically to Red or something?
Also maybe try this for the Style definition
<Style x:Key="ErrorIconPath" TargetType="{x:Type Path}">
Third suggestion would be to move the style definition from the App to your Page or even to your Control itself.
To be sure there will be no default styles applied, try
OverridesDefaultStyle="True"
Hope this helps :)

Getting text color from Silverlight RichTextBox

I have a problem with the getting the RichTextBox`s text color. There is a method about it but i was fail with it. help me to use this method or is there any way to do this.
Here is the method
run.Foreground(DependencyProperty)
I'm not sure what that method is supposed to do, but in XAML you would use:
<RichTextBox Name="MyBox" Text="Some text" Foreground="Red" />
or you could bind it to a Brush property:
<RichTextBox Name="MyBox" Text="Some text" Foreground="{Binding myColor}" />
If you're trying to set it from code behind:
Brush myBrush = new SolidColorBrush(Color.Red);
MyBox.Foreground = myBrush;
I just find the answer of my question
((System.Windows.Media.SolidColorBrush)(run.Foreground)).Color.ToString()
with above code i can get the color of the text in hex.

binding to width property in code behind

I have a situation where I need to create View box with one button. The xaml for this is as below: Please observe Width property of viewbox. The Width should be increased/decreased according to a slider bar(moving to right increases it, to left decreases it). As listed below I know how to do it in xaml and it works fine. But my requirement is to be able to create viewbox in code behind and assign it the properties.
<WrapPanel x:Name="_wrpImageButtons" Grid.IsSharedSizeScope="True"
ScrollViewer.CanContentScroll="True" d:LayoutOverrides="Height"
Margin="5">
<Viewbox x:Name="_ScaleButton"
Width="{Binding Value, ElementName=ZoomSlider}" Stretch="Fill">
<CustomButton:_uscVCARSImagesButton x:Name="_btnImage1"/>
</Viewbox>
</WrapPanel>
Thanks.
This should do what you want:
Viewbox x = new Viewbox();
Binding bnd = new Binding("Value") { ElementName = "ZoomSlider"};
BindingOperations.SetBinding(x, Viewbox.WidthProperty, bnd);
// ... Code to insert the Viewbox into the WrapPanel etc.
You can create the binding relatively easily in Code Behind:
var widthBinding = new Binding("Value") { ElementName = "ZoomSlider" };
_ScaleButton.SetBinding(FrameworkElement.WidthProperty, widthBinding);

Align bottoms of text in controls

The following snippet:
<Window x:Class="Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<StackPanel Orientation="Horizontal"
VerticalAlignment="Center"
HorizontalAlignment="Center">
<Label Content="Name:"/>
<Label Content="Itzhak Perlman" FontSize="44"/>
</StackPanel>
</Grid>
</Window>
Renders the following:
Is there any way I can set in the Labels' styles so that their text bottoms should be aligned?
I have the same question with TextBlocks as well.
NOTE: since I've been struggling with this issue for a while, please post only certains answers that you know that work.
I already tried: VerticalAlignment, VerticalContentAlignment, Padding, Margin. Is there anything else I am not aware of?
I've read this post, but it doesn't talk about a scenario of different font size.
UPDATE: The problem is, that even Padding is set to 0 there is still an indeterminate space around the font, within the ContentPresenter area. this space varies on the font size.
If I could control this space I would be in a better situation.
Thanks
Another fairly simple solution:
1) Use TextBlock controls instead of Labels. The reason being that TextBlock is lighter weight than Label - see http://joshsmithonwpf.wordpress.com/2007/07/04/differences-between-label-and-textblock/
2) Use the LineHeight and LineStackingStrategy = BlockLineHeight for your TextBlock style. This will align the two at their baseline easily.
<StackPanel Orientation="Horizontal"
VerticalAlignment="Center"
HorizontalAlignment="Center">
<StackPanel.Resources>
<Style TargetType="TextBlock">
<Setter Property="LineHeight" Value="44pt"/>
<Setter Property="LineStackingStrategy" Value="BlockLineHeight"/>
</Style>
</StackPanel.Resources>
<TextBlock Text="Name:"/>
<TextBlock Text="Itzhak Perlman" FontSize="44"/>
</StackPanel>
I really like the creative solutions that are presented here but I do think that in the long run (pun intended) we should use this:
<TextBlock>
<Run FontSize="20">What</Run>
<Run FontSize="36">ever</Run>
<Run FontSize="12" FontWeight="Bold">FontSize</Run>
</TextBlock>
The only thing that is missing from the Run element is databinding of the Text property but that might be added sooner or later.
A Run will not fix the alignment of labels and their textboxes but for many simple situation the Run will do quite nicely.
There is no XAML only solution, you have to use code behind. Also, even with code-behind, there's no general solution for this, because what if your text is multi-line? Which baseline should be used in that case? Or what if there are multiple text elements in your template? Such as a header and a content, or more, which baseline then?
In short, your best bet is to align the text manually using top/bottom margins.
If you're willing to make the assumption that you have a single text element, you can figure out the pixel distance of the baseline from the top of the element by instantiating a FormattedText object with all the same properties of the existing text element. The FormattedText object has a double Baseline property which holds that value. Note that you still would have to manually enter a margin, because the element might not sit exactly against the top or bottom of its container.
See this MSDN forum post: Textbox Baseline
Here's a method I wrote that extracts that value. It uses reflection to get the relevant properties because they are not common to any single base class (they are defined separately on Control, TextBlock, Page, TextElement and maybe others).
public double CalculateBaseline(object textObject)
{
double r = double.NaN;
if (textObject == null) return r;
Type t = textObject.GetType();
BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public;
var fontSizeFI = t.GetProperty("FontSize", bindingFlags);
if (fontSizeFI == null) return r;
var fontFamilyFI = t.GetProperty("FontFamily", bindingFlags);
var fontStyleFI = t.GetProperty("FontStyle", bindingFlags);
var fontWeightFI = t.GetProperty("FontWeight", bindingFlags);
var fontStretchFI = t.GetProperty("FontStretch", bindingFlags);
var fontSize = (double)fontSizeFI.GetValue(textObject, null);
var fontFamily = (FontFamily)fontFamilyFI.GetValue(textObject, null);
var fontStyle = (FontStyle)fontStyleFI.GetValue(textObject, null);
var fontWeight = (FontWeight)fontWeightFI.GetValue(textObject, null);
var fontStretch = (FontStretch)fontStretchFI.GetValue(textObject, null);
var typeFace = new Typeface(fontFamily, fontStyle, fontWeight, fontStretch);
var formattedText = new FormattedText(
"W",
CultureInfo.CurrentCulture,
FlowDirection.LeftToRight,
typeFace,
fontSize,
Brushes.Black);
r = formattedText.Baseline;
return r;
}
EDIT: Shimmy, in response to your comment, I don't believe you've actually tried this solution, because it works. Here's an example:
Here's the XAML:
<StackPanel>
<StackPanel.Resources>
<Style TargetType="TextBlock">
<Setter Property="Margin" Value="0,40,0,0"/>
</Style>
</StackPanel.Resources>
<StackPanel Orientation="Horizontal">
<TextBlock Name="tb1" Text="Lorem " FontSize="10"/>
<TextBlock Name="tbref" Text="ipsum"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Name="tb2" Text="dolor " FontSize="20"/>
<TextBlock Text="sit"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Name="tb3" Text="amet " FontSize="30"/>
<TextBlock Text="consectetuer"/>
</StackPanel>
</StackPanel>
And here's the code behind that achieves this
double baseRef = CalculateBaseline(tbref);
double base1 = CalculateBaseline(tb1) - baseRef;
double base2 = CalculateBaseline(tb2) - baseRef;
double base3 = CalculateBaseline(tb3) - baseRef;
tb1.Margin = new Thickness(0, 40 - base1, 0, 0);
tb2.Margin = new Thickness(0, 40 - base2, 0, 0);
tb3.Margin = new Thickness(0, 40 - base3, 0, 0);
<TextBlock>
<InlineUIContainer BaselineAlignment="Baseline"><TextBlock>Small</TextBlock></InlineUIContainer>
<InlineUIContainer BaselineAlignment="Baseline"><TextBlock FontSize="50">Big</TextBlock></InlineUIContainer>
</TextBlock>
This should works well. Experiment with Baseline/Bottom/Center/Top.
XAML designer supports aligning TextBlock controls by baseline at design time:
This assigns fixed margins to your controls. As long as font sizes do not change at run time, the alignment will be preserved.
I actually found a simple answer based on Aviad's.
I created a converter that contains Aviad's function that accepts the element itself and returns calculated Thickness.
Then I set up
<Style TargetType="TextBlock">
<Setter Property="Margin"
Value="{Binding RelativeSource={RelativeSource Self}, Converter={StaticResource converters:TextAlignmentMarginConverter}}" />
</Style>
The disadvantage is that this is obviously occupies the original Margin property, since a TextBlock doesn't have a template so we can't set it via TemplateBinding.
In the blog article XAML text improvements in Windows 8.1 is explained how you can align two TextBlocks of different font sizes by their baseline. The trick is TextLineBounds="TrimToBaseline" combined with VerticalAlignment="Bottom". That removes the size below their baseline, and then moves the TextBlocks down. You can then move it them back up to the desired height by setting a Margin on a container you put them in.
Sample:
<Grid Margin="some margin to lift the TextBlocks to desired height">
<TextBlock Text="{x:Bind ViewModel.Name, Mode=OneWay}"
Style="{StaticResource HeaderTextBlockStyle}"
VerticalAlignment="Bottom"
TextLineBounds="TrimToBaseline" />
<TextBlock Text="{x:Bind ViewModel.Description.Yield, Mode=OneWay}"
Style="{StaticResource SubheaderTextBlockStyle}"
VerticalAlignment="Bottom"
HorizontalAlignment="Right"
TextLineBounds="TrimToBaseline" />
</Grid>

Silverlight text around an image

Im am trying to wrap text around an image as one would use the html float property. Is there a way to acomplish this in silverlight 3?
Thanks
I tackled this issue a while back. There is not really a good way that I know of. This will work though it's just painful.
In order to simplify the explanation why don't we assume that the image is in the upper right corner of the page and the text needs to be to the left and below the image.
Start by placing the TextBlock and the Image side-by-side.
Calculate the bottom most point of the TextBlock and the bottom most point of the image. (Use their top margins and actual heights.
While the TextBlock is the larger you move a word at a time into a newly created TextBlock below the image. This creates the illusion of wrapping text.
leftText.Text = textToWrap;
bottomText.Text = string.Empty;
Stack<string> wordsToMove = new Stack<string>();
double imageBottomPoint = image1.ActualHeight + image1.Margin.Top;
while ((leftText.ActualHeight + leftText.Margin.Top) > (imageBottomPoint + 14))
{
int lastSpace = leftText.Text.LastIndexOf(' ');
string textToMove = leftText.Text.Substring(lastSpace).Trim();
BlockedText.Text = leftText.Text.Remove(lastSpace);
wordsToMove.Push(textToMove + ' ');
}
StringBuilder sb = new StringBuilder(bottomText.Text);
while (wordsToMove.Count > 0)
{
sb.Append(wordsToMove.Pop());
}
bottomText.Text = sb.ToString();
You need to look RichTextBox and FlowDocument if it is WPF and RichTextBox if Silverlight 4.0.
Silverlight 4.0 Solution
<RichTextBox TextWrapping="Wrap" IsReadOnly="False">
<Paragraph>
More text here ..
<InlineUIContainer>
<Image Source="abc.jpg"/>
</InlineUIContainer>
more and more text here;
<LineBreak />
</Paragraph>
</RichTextBox>
WPF Solution-
<RichTextBox>
<FlowDocument IsEnabled="true">
<Paragraph>
Text text ..
<Button Margin="10,0,10,0" Content="A Button Float"/>
More text..
</Paragraph>
<Paragraph TextAlignment="Center">
<Image Source="abc.jpg"/>
text text..
</Paragraph>
</FlowDocument>
</RichTextBox>

Resources