Thanks to Leom's answer I was able to add a FlowDocument to a StackPanel by wrapping it in a FlowDocumentReader.
But now I have two problems:
it seems only the first FlowDocumentReader is added and the rest ignored
there is an unwanted margin that I can't get rid of
How can I add multiple FlowDocumentReaders to a StackPanel without the unwanted margin?
alt text http://www.deviantsart.com/upload/1ndiqqe.png
XAML:
<Window x:Class="TestFlowdoc23432.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="200" Width="300">
<StackPanel Margin="10">
<ContentControl x:Name="MainArea"/>
</StackPanel>
</Window>
Code Behind:
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
namespace TestFlowdoc23432
{
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
StackPanel sp = new StackPanel();
TextBlock tb1 = new TextBlock();
tb1.Text = "first text block";
sp.Children.Add(tb1);
TextBlock tb2 = new TextBlock();
tb2.Text = "second text block";
sp.Children.Add(tb2);
sp.Children.Add(GetFlowDocumentReader("first flow document reader"));
sp.Children.Add(GetFlowDocumentReader("second flow document reader"));
MainArea.Content = sp;
}
FlowDocumentReader GetFlowDocumentReader(string text)
{
FlowDocumentReader fdr = new FlowDocumentReader();
FlowDocument fd = new FlowDocument();
fdr.Document = fd;
fdr.Margin = new Thickness(0);
Paragraph par = new Paragraph();
par.Margin = new Thickness(0);
fd.Blocks.Add(par);
Run r = new Run(text);
par.Inlines.Add(r);
return fdr;
}
}
}
To make the text appear to the left you need to set the pagepadding property on your flowdocument as follows:
fd.PagePadding = new Thickness(0);
the reason that you only seem to get the first reader is becuase it fills the space available (move it to be the first object and you will not see the textblocks).
If you change the FlowDocumentReader to be a FlowDocumentScrollViewer and use the VerticalScrollBarVisibility property then you can get the desired effect. The following is your GetFlowDocumentReader method with the changes applied:
FlowDocumentScrollViewer GetFlowDocumentReader(string text)
{
FlowDocumentScrollViewer fdr = new FlowDocumentScrollViewer();
FlowDocument fd = new FlowDocument();
fdr.Document = fd;
fdr.Margin = new Thickness(0);
Paragraph par = new Paragraph();
par.Margin = new Thickness(0);
fd.Blocks.Add(par);
Run r = new Run(text);
par.Inlines.Add(r);
fd.PagePadding = new Thickness(0);
fdr.VerticalScrollBarVisibility = ScrollBarVisibility.Hidden;
return fdr;
}
Related
I'm trying to load RTF text from database and display it into datatemplate of custom RichTextBox .
I would like to get the text with style , with code the matter is simple but when I'm trying to use <GridViewDataColumn.CellTemplate> <GridViewDataColumn.CellTemplate/> , it got difficult
Xaml code:
<telerik:GridViewDataColumn DataMemberBinding="{Binding document}" Width="*" x:Name="Description" IsReadOnly="True">
<telerik:GridViewDataColumn.CellTemplate>
<DataTemplate >
<local:UC_Description x:Name="richtext">
</local:UC_Description>
</DataTemplate>
</telerik:GridViewDataColumn.CellTemplate>
C# code:
List= new Controller().GetAll();
foreach (Model item in List)
{
RtfFormatProvider provider = new RtfFormatProvider();
DocumentFormatProvidersManager.RegisterFormatProvider(provider);
byte[] byteArray = Encoding.ASCII.GetBytes(item.Description);
document = provider.Import(byteArray);
FlowDocument flow = new FlowDocument();
}
GridViewList.ItemsSource = null;
GridViewList.ItemsSource = List;
this.DataContext = this;
}
public RadDocument ImportXaml(string content)
{
RtfFormatProvider provider = new RtfFormatProvider();
return provider.Import(text);
}
public string RtfToPlainText(string rtf)
{
byte[] byteArray = Encoding.ASCII.GetBytes(rtf);
var flowDocument = new FlowDocument();
TextRange tr;
using (MemoryStream ms = new MemoryStream(byteArray))
{
tr = new TextRange(flowDocument.ContentStart, flowDocument.ContentEnd);
tr.Load(ms, DataFormats.Rtf);
}
return tr.Text;
}
How can I display text from RTF content in a data template?
A template is a template and there is no UC_Description or RichTextBox until it has been applied at runtime.
What you could do is to handle the Loaded event for the UserControl and then set the Document property of the RichTextBox to your document:
XAML:
<telerik:GridViewDataColumn.CellTemplate>
<DataTemplate >
<local:UC_Description Loaded="OnLoaded" />
</DataTemplate>
</telerik:GridViewDataColumn.CellTemplate>
Code:
private void OnLoaded(object sender, RoutedEventArgs e)
{
UC_Description uc = (UC_Description)sender;
uc.richTextBox.Document = ...;
}
Is there a way to implement an image within a TextBlock rather than outside of it? Android has a feature called SpaanableStringBuilder which allows the user to create text with different appearances. Does UWP have something similar?
MyTextBlock.Text = "Google" + ? + "icon";
As Raymond said, in UWP, RichTextBlock is needed for image and text mixing.
With Xaml
<RichTextBlock>
<Paragraph>
<Run Text="Something..."/>
<InlineUIContainer>
<Image Source="your_image_url" Width="20" Height="20"/>
</InlineUIContainer>
<Run Text="Something..."/>
</Paragraph>
</RichTextBlock>
With Code
var richTextBlock = new RichTextBlock();
var para = new Paragraph();
para.Inlines.Add(new Run() { Text = "Something..." });
var imgContainer = new InlineUIContainer();
var img = new Image();
img.Source = new BitmapImage(new Uri("your_image_url"));
imgContainer.Child = img;
para.Inlines.Add(imgContainer);
para.Inlines.Add(new Run() { Text = "Something..." });
richTextBlock.Blocks.Add(para);
Or you could write it this way, which more closely mirrors the XAML.
var richTextBlock = new RichTextBlock()
{
Blocks = {
new Paragraph {
Inlines = {
new Run { Text = "Something" },
new InlineUIContainer {
Child = new Image {
Source = new BitmapImage(new Uri("your_image_url"))
}
},
new Run { Text = "Something..."}
}
}
}
};
I created a new TabItem Style which looks the way I wanted. But now it screws up the positions of all the controls which are placed on the TabItem. It moves them from the top left area to the right bottom area of the TabItem. Any help would be highly appreciated. (Yes, I am sure I need the style in C# NOT in XAML)
var functionReturnValue = new Style();
ControlTemplate L_NewControlTemplate = new ControlTemplate(typeof(TabItem));
FrameworkElementFactory L_ElemFactory = new FrameworkElementFactory(typeof(Border));
L_ElemFactory.SetBinding(Border.FocusVisualStyleProperty, new System.Windows.Data.Binding { RelativeSource = System.Windows.Data.RelativeSource.TemplatedParent, Path = new PropertyPath("FocusVisualStyle") });
L_ElemFactory.SetBinding(Border.BackgroundProperty, new System.Windows.Data.Binding { RelativeSource = System.Windows.Data.RelativeSource.TemplatedParent, Path = new PropertyPath("Background") });
L_ElemFactory.SetBinding(Border.BorderBrushProperty, new System.Windows.Data.Binding { RelativeSource = System.Windows.Data.RelativeSource.TemplatedParent, Path = new PropertyPath("BorderBrush") });
L_ElemFactory.SetBinding(Border.BorderThicknessProperty, new System.Windows.Data.Binding { RelativeSource = System.Windows.Data.RelativeSource.TemplatedParent, Path = new PropertyPath("BorderThickness") });
//L_ElemFactory.SetValue(Border.CornerRadiusProperty, new CornerRadius(0,12,0,0));
L_ElemFactory.SetValue(Border.SnapsToDevicePixelsProperty, true);
FrameworkElementFactory L_ContentPresenter = new FrameworkElementFactory(typeof(ContentPresenter));
L_ContentPresenter.SetValue(ContentPresenter.ContentSourceProperty, "Header");
L_ContentPresenter.SetBinding(ContentPresenter.HorizontalAlignmentProperty, new System.Windows.Data.Binding { RelativeSource = System.Windows.Data.RelativeSource.TemplatedParent, Path = new PropertyPath("HorizontalContentAlignment") });
L_ContentPresenter.SetBinding(ContentPresenter.VerticalAlignmentProperty, new System.Windows.Data.Binding { RelativeSource = System.Windows.Data.RelativeSource.TemplatedParent, Path = new PropertyPath("VerticalContentAlignment") });
L_ContentPresenter.SetBinding(ContentPresenter.SnapsToDevicePixelsProperty, new System.Windows.Data.Binding { RelativeSource = System.Windows.Data.RelativeSource.TemplatedParent, Path = new PropertyPath("SnapsToDevicePixels") });
L_ElemFactory.AppendChild(L_ContentPresenter);
L_NewControlTemplate.VisualTree = L_ElemFactory;
Trigger NewTrigger;
//Trigger IsEnabled = true
NewTrigger = new Trigger { Property = TabItem.IsEnabledProperty, Value = true };
NewTrigger.Setters.Add(new Setter(TabItem.ForegroundProperty, F_Foreround));
NewTrigger.Setters.Add(new Setter(TabItem.BackgroundProperty, F_Background));
L_NewControlTemplate.Triggers.Add(NewTrigger);
//Trigger MouseOver
NewTrigger = new Trigger { Property = TabItem.IsMouseOverProperty, Value = true };
NewTrigger.Setters.Add(new Setter(TabItem.ForegroundProperty, F_Foreround));
NewTrigger.Setters.Add(new Setter(TabItem.BackgroundProperty, F_MouseOver));
L_NewControlTemplate.Triggers.Add(NewTrigger);
//Trigger Selected
NewTrigger = new Trigger { Property = TabItem.IsSelectedProperty, Value = true };
NewTrigger.Setters.Add(new Setter(TabItem.ForegroundProperty, F_Foreround));
NewTrigger.Setters.Add(new Setter(TabItem.BackgroundProperty, F_Background));
L_NewControlTemplate.Triggers.Add(NewTrigger);
//Trigger Selected
NewTrigger = new Trigger { Property = TabItem.IsSelectedProperty, Value = false };
NewTrigger.Setters.Add(new Setter(TabItem.BackgroundProperty, L_IsDeActive));
L_NewControlTemplate.Triggers.Add(NewTrigger);
functionReturnValue.Setters.Add(new Setter(TabItem.FocusVisualStyleProperty, null));
functionReturnValue.Setters.Add(new Setter(TabItem.BackgroundProperty, F_Background));
functionReturnValue.Setters.Add(new Setter(TabItem.BorderBrushProperty, Brushes.Green));
functionReturnValue.Setters.Add(new Setter(TabItem.BorderThicknessProperty, new Thickness(0)));
functionReturnValue.Setters.Add(new Setter(TabItem.ForegroundProperty, F_Foreround));
functionReturnValue.Setters.Add(new Setter(TabItem.HorizontalContentAlignmentProperty, System.Windows.HorizontalAlignment.Center));
functionReturnValue.Setters.Add(new Setter(TabItem.VerticalContentAlignmentProperty, System.Windows.VerticalAlignment.Center));
functionReturnValue.Setters.Add(new Setter(TabItem.PaddingProperty, new Thickness(0)));
functionReturnValue.Setters.Add(new Setter(TabItem.MarginProperty, new Thickness(-4, -4, 0, 0)));
functionReturnValue.Setters.Add(new Setter(TabItem.TemplateProperty, L_NewControlTemplate));
return functionReturnValue;
So it turns out your first problem is these two lines:
functionReturnValue.Setters.Add(new Setter(TabItem.HorizontalContentAlignmentProperty, System.Windows.HorizontalAlignment.Center));
functionReturnValue.Setters.Add(new Setter(TabItem.VerticalContentAlignmentProperty, System.Windows.VerticalAlignment.Center));
Just omit those; they're acting on the tab item content, not on the header.
To restyle the header, you have a lot of options.
This will put a 20 unit margin around your content presenter:
L_ContentPresenter.SetValue(ContentPresenter.MarginProperty, new Thickness(20));
20's pretty arbitrary; of course you can use your own values. This will give it 20 unit side margins and 10 unit top/bottom margins:
L_ContentPresenter.SetValue(ContentPresenter.MarginProperty, new Thickness(20, 10, 20, 10));
You could also put a Border or something inside the header control template, surrounding the ContentPresenter, and do something with the padding or margins of that containing control. This kind of thing is infinitely easier to work with in XAML, so I'm not going to the trouble of doing that in C#.
You could have the TabItem style set HeaderTemplate, which is a DataTemplate:
var headerTemplate = new DataTemplate();
var label = new FrameworkElementFactory(typeof(Label));
label.SetBinding(Label.ContentProperty, new Binding());
label.SetValue(Label.MarginProperty, new Thickness(16, 12, 16, 12));
headerTemplate.VisualTree = label;
functionReturnValue.Setters.Add(new Setter(TabItem.HeaderTemplateProperty, headerTemplate));
In closing, I'd like to reiterate that whatever you need to do at runtime to Styles, you can do more easily and far more maintainably in XAML than in C#.
I'm trying to style the Coding4Fun InputPrompt control to set a border on the textbox element and change the unselected colour in code.
I've not been able to find any examples, and visual studio doesn't recognise the control properly (InputPrompt is displayed in red with no intellisense, but the project runs fine).
I've managed to set some colours and update the buttons, but no success on the textbox.
Can anyone point me in the right direction please?
Here is what I have so far:
var input = new InputPrompt
{
Title = "Title",
Message = "My Message",
IsCancelVisible = true,
Background = new SolidColorBrush(Color.FromArgb(0xCC, 0x00, 0x00, 0x00)),
Foreground = new SolidColorBrush(Colors.White)
};
input.Completed += input_Completed;
input.InputScope = new InputScope
{
Names = {new InputScopeName() {NameValue = InputScopeNameValue.TelephoneNumber}}
};
foreach (var button in input.ActionPopUpButtons)
{
button.Foreground = new SolidColorBrush(Colors.White);
button.BorderBrush = new SolidColorBrush(Colors.White);
button.Margin = new Thickness(0,5,0,0);
}
input.BorderThickness = new Thickness(5.0);
input.Show();
I need to generate the image programmatically, so using an tag in the xaml isn't an option. I tried also to run at, when the window is loaded, but
Running the program just gives me a blank screen:
My .CS
namespace WpfApplication2
{
public partial class MainWindow : Window
{
public Image anImage;
public MainWindow()
{
InitializeComponent();
anImage = new Image();
anImage.Visibility = Visibility.Visible;
anImage.Width = 120;
anImage.Height = 310;
anImage.HorizontalAlignment = HorizontalAlignment.Left;
anImage.VerticalAlignment = VerticalAlignment.Top;
anImage.Margin = new Thickness(500, 500, 0, 0);
BitmapImage bmImage = new BitmapImage();
bmImage.BeginInit();
bmImage.UriSource = new Uri("balloonB.png", UriKind.Relative);
bmImage.EndInit();
anImage.Source = bmImage;
anImage.Stretch = Stretch.None;
this.AddVisualChild(anImage);
this.InvalidateVisual();
}
}
}
My XAML
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="1024" Width="1280" ResizeMode="NoResize"
WindowStartupLocation="CenterScreen" WindowState="Maximized">
<Grid Width="1280" Height="1024">
</Grid>
</Window>
There are at least two things wrong with your code.
First, you should make sure that the image file can be loaded at runtime. The easiest way is to add the file to your Visual Studio project, perhaps in a folder named "Images". The Build Action of the file has to be set to Resource, but this is the default for image files anyway. Now you can access this image resource file in code behind by means of a Pack URI (or a Resource Pack URI to be more precise). Given the folder name "Images", that URI would look like this:
pack://application:,,,/Images/balloonB.png
Second, you should not use AddVisualChild to add the Image control to your MainWindow. Instead, add it to the top-level Grid by setting the x:Name attribute on the Grid in XAML, and then using the auto-generated member variable with that name in code-behind.
<Window ...>
<Grid x:Name="rootGrid" Width="1280" Height="1024">
</Grid>
</Window>
Add the Image control to the Grid:
rootGrid.Children.Add(anImage);
Putting it all together and omitting unnecessary property settings, your code would look like this:
var anImage = new Image();
anImage.Width = 120;
anImage.Height = 310;
anImage.HorizontalAlignment = HorizontalAlignment.Left;
anImage.VerticalAlignment = VerticalAlignment.Top;
anImage.Margin = new Thickness(500, 500, 0, 0);
anImage.Source = new BitmapImage(new Uri("pack://application:,,,/Images/balloonB.png"));
rootGrid.Children.Add(anImage);
Or, a little shorter:
var anImage = new Image
{
Width = 120,
Height = 310,
HorizontalAlignment = HorizontalAlignment.Left,
VerticalAlignment = VerticalAlignment.Top,
Margin = new Thickness(500, 500, 0, 0),
Source = new BitmapImage(new Uri("pack://application:,,,/Images/balloonB.png"))
};
rootGrid.Children.Add(anImage);
I find many times that a full pack Uri is a bit much and that a simplified Uri works just as well if not better, just be sure that your image build property is configured as MSBuild Resource:
Image anImage = new Image();
anImage.Visibility = Visibility.Visible;
anImage.Width = 120;
anImage.Height = 310;
anImage.HorizontalAlignment = HorizontalAlignment.Left;
anImage.VerticalAlignment = VerticalAlignment.Top;
BitmapImage bmImage = new BitmapImage(new Uri(#"pack://application:,,,/yournameSpace;component/Subfolder/balloonB.png"));
bmImage.BeginInit();
bmImage.EndInit();
anImage.Source = bmImage;
anImage.Stretch = Stretch.None;
gr.Children.Add(anImage);
Xaml
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="1024" Width="1280" ResizeMode="NoResize"
WindowStartupLocation="CenterScreen" WindowState="Maximized">
<Grid Name="gr" Width="1280" Height="1024">
</Grid>
</Window>
There might be a problem with this line:
anImage.Margin = new Thickness(500, 500, 0, 0);
I renamed my Grid to gr and tried the following code and it works, I used the ImageBrush to draw the image:
Image anImage = new Image();
anImage.Visibility = Visibility.Visible;
anImage.Width = 120;
anImage.Height = 310;
anImage.HorizontalAlignment = HorizontalAlignment.Left;
anImage.VerticalAlignment = VerticalAlignment.Top;
//anImage.Margin = new Thickness(500, 500, 0, 0);
BitmapImage bmImage = new BitmapImage();
bmImage.BeginInit();
bmImage.UriSource = new Uri("balloonB.png", UriKind.Relative);
bmImage.EndInit();
ImageBrush ib = new ImageBrush(bmImage);
anImage.Source = ib.ImageSource;
gr.Children.Add(anImage);
Xaml
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="1024" Width="1280" ResizeMode="NoResize"
WindowStartupLocation="CenterScreen" WindowState="Maximized">
<Grid Name="gr" Width="1280" Height="1024">
</Grid>
</Window>