I am trying to print a Canvas that contains a glyph element using Silverlight 5's vector printing capacity. Everything works fine except that glyphs do not get printed. Are glyphs supported by vector printing? If so, what am I doing wrong? I am trying to print the following canvas that shows up correctly on the screen:
<Canvas x:Name="canvasToPrint" Margin="-96,-34,0,0" Grid.ColumnSpan="2" Background="AliceBlue">
<Rectangle Fill="Blue" Width="39" Height="36"/>
<Glyphs Name="a0" Fill="#FF000000" FontUri="36481AB7-37EB-642E-4A01-FB63CC6ED952.odttf" FontRenderingEmSize="11.04" StyleSimulations="None" OriginX="72.024" OriginY="82.464" UnicodeString="Hello, World!" Indices=",61.957;,50;,22.826;,22.826;,53.261;,25;,21.739;,89.13;,53.261;,34.783;,22.826;,52.174;">
</Glyphs>
<Button Height="25" Content="Print" Click="Button_Click"/>
</Canvas>
With the following code for a print button:
private void Button_Click(object sender, RoutedEventArgs e)
{
PrintDocument doc = new PrintDocument();
doc.BeginPrint += new EventHandler<BeginPrintEventArgs>(BeginPrinting);
doc.PrintPage += new EventHandler<PrintPageEventArgs>(PrintNextPage);
doc.Print("vector");
}
private void BeginPrinting(Object sender, BeginPrintEventArgs e)
{
}
private void PrintNextPage(Object sender, PrintPageEventArgs e)
{
e.PageVisual = canvasToPrint;
e.HasMorePages = false;
}
Note that everything prints correctly if I switch doc.Print to doc.PrintBitmap.
Related
I have trouble with moving a canvas in a Window.
<Canvas x:Name="Canvas1" Height="200" Grid.Column="1" Margin="10,15,92,54" Grid.Row="1" Background="#FFECECEC" Grid.RowSpan="2" MouseDown="Canvas_MouseDown" MouseUp="Canvas_MouseUp" MouseMove="Canvas_MouseMove" >
<TextBox Height="100" Width="100" Margin="50,50,327,65" Background="Red"/>
<TextBox Height="100" Width="100" Margin="10,15,327,65" Background="Blue" />
<Canvas.RenderTransform>
<TransformGroup>
<TranslateTransform x:Name="translate" />
</TransformGroup>
</Canvas.RenderTransform>
</Canvas>
This is code behind:
private void Canvas_MouseDown(object sender, MouseButtonEventArgs e)
{
Canvas1.CaptureMouse();
point = Mouse.GetPosition(Grid1);
}
private void Canvas_MouseMove(object sender, MouseEventArgs e)
{
if (Canvas1.IsMouseCaptured)
{
translate.X = e.GetPosition(Grid1).X - point.X;
translate.Y = e.GetPosition(Grid1).Y - point.Y;
}
}
private void Canvas_MouseUp(object sender, MouseButtonEventArgs e)
{
Canvas1.ReleaseMouseCapture();
}
First time, it seem woork fine.
But second time i try to click on my canvas, this move but from initial position.
How can i fix it?
When initializing point on mouse down, subtract the current translation:
private void Canvas1_MouseDown(object sender, MouseButtonEventArgs e)
{
Canvas1.CaptureMouse();
point = Mouse.GetPosition(Grid1);
point.X -= translate.X;
point.Y -= translate.Y;
}
Alternatively, always only add the difference vector:
private void Canvas1_MouseDown(object sender, MouseButtonEventArgs e)
{
Canvas1.CaptureMouse();
point = Mouse.GetPosition(Grid1);
}
private void Canvas1_MouseMove(object sender, MouseEventArgs e)
{
if (Canvas1.IsMouseCaptured)
{
var p = e.GetPosition(Grid1);
var diff = p - point;
point = p;
translate.X += diff.X;
translate.Y += diff.Y;
}
}
Also make sure the Grid doesn't position the Canvas, by setting the Canvas alignment to Top/Left:
<Canvas x:Name="Canvas1" HorizontalAlignment="Left" VerticalAlignment="Top" ...>
And probably don't set a Margin, but instead initialize the TranslateTransform appropriately.
Here is a setup: I have a textbox with a numberic value. According to the requirements every time anybody changes that value an accompanying comment needs to be provided. So visually there must be another textbox for the comment that should be displayed right next to the first one. Ideally the comment textbox needs to be placed in a callout that originates from the value textbox and displayed on the right from it overlaying anything what's underneath of it just like on this picture:
I know how to do easily it in CSS and HTML.
I have to do the same in Silverlight now.
Unfortunately I am not very strong in it, so what I am specifically asking about is how having 2 textboxes make one of them appear next to another (on the right overlaying whatever controls are underneath it) with as less XAML and code as possible.
Use a ToolTip, and set the Placement such that it appears to the right. in XAML, you can template your ToolTip to look however you want, even if that means mimicking the TextBox appearance.
This is the purpose of the ToolTip, and I feel strongly that you should always use the right tool for the right job. :)
I hope this helps. Let us know if you need code samples.
EDIT: Added the following code samples:
<TextBox ToolTipService.Placement="Right">
<ToolTipService.ToolTip>
<TextBox Text="{Binding CalloutText, Mode=OneWay}" IsReadOnly="True"/>
</ToolTipService.ToolTip>
</TextBox>
Ok, I ended up writing my own behaviour
namespace MyNamespace
{
public class CommentBehavior : Behavior<TextBox>
{
private readonly TimeSpan howLongWeWaitBeforePopupCloses = TimeSpan.FromMilliseconds(200);
private DispatcherTimer popupClosingTimer;
public static DependencyProperty PopupProperty = DependencyProperty.Register("Popup", typeof(Popup), typeof(CommentBehavior), new PropertyMetadata(null));
public Popup Popup
{
get { return (Popup)this.GetValue(PopupProperty); }
set { this.SetValue(PopupProperty, value); }
}
protected override void OnAttached()
{
this.popupClosingTimer = new DispatcherTimer();
this.popupClosingTimer.Stop();
this.popupClosingTimer.Interval = howLongWeWaitBeforePopupCloses;
this.popupClosingTimer.Tick += this.ClosePopup;
this.AssociatedObject.GotFocus += this.GotFocus;
this.AssociatedObject.LostFocus += this.LostFocus;
this.Popup.Child.GotFocus += PopupChild_GotFocus;
this.Popup.Child.LostFocus += PopupChild_LostFocus;
}
private void PopupChild_LostFocus(object sender, RoutedEventArgs e)
{
this.popupClosingTimer.Start();
}
private void PopupChild_GotFocus(object sender, RoutedEventArgs e)
{
this.popupClosingTimer.Stop();
}
protected override void OnDetaching()
{
this.AssociatedObject.GotFocus -= this.GotFocus;
this.AssociatedObject.LostFocus -= this.LostFocus;
this.Popup.GotFocus -= PopupChild_GotFocus;
this.popupClosingTimer.Tick -= this.ClosePopup;
this.popupClosingTimer = null;
}
private void ClosePopup(object sender, EventArgs e)
{
this.Popup.IsOpen = false;
this.popupClosingTimer.Stop();
}
protected void GotFocus(object sender, RoutedEventArgs e)
{
this.popupClosingTimer.Stop();
this.Popup.IsOpen = true;
var at = this.CalculatePopupPosition();
this.Popup.HorizontalOffset = at.X;
this.Popup.VerticalOffset = at.Y;
}
private Point CalculatePopupPosition()
{
var owner = this.AssociatedObject;
var transformation = owner.TransformToVisual(Application.Current.RootVisual);
var at = transformation.Transform(new Point(owner.ActualWidth, 0));
return at;
}
protected void LostFocus(object sender, RoutedEventArgs e)
{
this.popupClosingTimer.Start();
}
}
}
And the following XAML
<Grid x:Name="LayoutRoot" Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Background="Red">
<TextBox Width="200" Text="0.01">
<i:Interaction.Behaviors>
<local:CommentBehavior>
<local:CommentBehavior.Popup>
<Popup>
<TextBox Text="Comment" />
</Popup>
</local:CommentBehavior.Popup>
</local:CommentBehavior>
</i:Interaction.Behaviors>
</TextBox>
</StackPanel>
</Grid>
I'm kinda confused with some problem, I'm doing a project where the user should be able to design questions with radio buttons, combo box, etc (kinda like toolbox from VS10 to design your XAML).
So far I can drag and drop an UIElement that I previously created, problem comes when the user creates a new element from my toolbox, I can't find the way to make that new UIElement to get the same events from my previosly created UIElement. Take a look at the code
<Window x:Class="WpfApplication1.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">
<Grid>
<Canvas Height="190" HorizontalAlignment="Left" Margin="158,41,0,0" Name="canvas1" VerticalAlignment="Top" Width="322" AllowDrop="True">
<Button Content="PROBANDO" Height="23" Name="button" Width="75" Canvas.Left="113" Canvas.Top="43" PreviewMouseDown="button_PreviewMouseDown" PreviewMouseMove="button_PreviewMouseMove" MouseUp="button_MouseUp" IsEnabled="True" />
<TextBlock Canvas.Left="99" Canvas.Top="147" Height="23" Name="textBlock" Text="" Width="107" />
</Canvas>
<ListBox Height="190" Name="listBox" Width="126" Margin="12,41,365,80" >
<ListBoxItem Content="Radio Button" Selected="radio_Selected" Name="radio" />
<ListBoxItem Content="Text" Selected="text_Selected" Name="text" />
<ListBoxItem Content="Combo Box" Name="combo" Selected="combo_Selected" />
</ListBox>
</Grid>
</Window>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
Point p;
private void button_MouseUp(object sender, MouseButtonEventArgs e)
{
button.ReleaseMouseCapture();
}
private void button_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
button.CaptureMouse();
p = e.GetPosition(canvas1);
}
private void button_PreviewMouseMove(object sender, MouseEventArgs e)
{
Point x = e.GetPosition(canvas1);
if (e.LeftButton == MouseButtonState.Pressed)
{
Canvas.SetLeft(button, Canvas.GetLeft(button) + (x.X - p.X));
Canvas.SetTop(button, Canvas.GetTop(button) + (x.Y - p.Y));
}
p = x;
}
private void generic_PreviewMouseDown(UIElement sender, MouseEventArgs e)
{
Point x = e.GetPosition(canvas1);
if (e.LeftButton == MouseButtonState.Pressed)
{
Canvas.SetLeft(sender, Canvas.GetLeft(sender) + (x.X - p.X));
Canvas.SetTop(sender, Canvas.GetTop(sender) + (x.Y - p.Y));
}
p = x;
}
private void radio_Selected(object sender, RoutedEventArgs e)
{
RadioButton newRadio = new RadioButton();
canvas1.Children.Add(newRadio);
newRadio.PreviewMouseDown += generic_PreviewMouseDown(newRadio,?????);
textBlock.Text = listBox.SelectedIndex.ToString();
}
private void text_Selected(object sender, RoutedEventArgs e)
{
TextBox newText = new TextBox();
canvas1.Children.Add(newText);
textBlock.Text = (String)listBox.SelectedIndex.ToString();
}
private void combo_Selected(object sender, RoutedEventArgs e)
{
Console.Write("Combo");
textBlock.Text = (String)listBox.SelectedIndex.ToString();
}
}
Thanks!
If all you want to do is handle the mouse down on the new RadioButton, change this line:
newRadio.PreviewMouseDown += generic_PreviewMouseDown(newRadio,?????);
To this:
newRadio.PreviewMouseDown += generic_PreviewMouseDown;
Edit
And then you need to change the generic_PreviewMouseDown to the following:
private void generic_PreviewMouseDown(object sender, MouseEventArgs e)
{
UIElement elem = sender as UIElement;
Point x = e.GetPosition(canvas1);
if (e.LeftButton == MouseButtonState.Pressed)
{
Canvas.SetLeft(elem, Canvas.GetLeft(elem) + (x.X - p.X));
Canvas.SetTop(elem, Canvas.GetTop(elem) + (x.Y - p.Y));
}
p = x;
}
I've created a bare bones example to try and figure out why the data being sent to the printer is so large. I'm sending one text box with "Printing text." as its content. This results in ~90MB being sent to the printer. Why is this so large?
Can someone please explain how I can avoid this?
Here is my example
<StackPanel x:Name="LayoutRoot" Orientation="Vertical">
<Button Content="Print" Click="Button_Click" Width="50" Height="20"/>
<TextBox x:Name="tbPrintableTextBox" Text="Printing test." Width="300" Height="20"/>
</StackPanel>
And the code:
public partial class Print : Page
{
PrintDocument pd;
public Print()
{
InitializeComponent();
// Create new a new PrintDocument object
pd = new PrintDocument();
pd.PrintPage += new EventHandler<PrintPageEventArgs>(pd_PrintPage);
}
// Executes when the user navigates to this page.
protected override void OnNavigatedTo(NavigationEventArgs e)
{
}
void pd_PrintPage(object sender, PrintPageEventArgs e)
{
e.PageVisual = tbPrintableTextBox;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
pd.Print("Print test");
}
}
http://forums.silverlight.net/forums/p/180585/409402.aspx
I am using slider control for an audio player in silverlight application. The slider is not moving while audio is playing.
The below one is my XAML code . How to get it?
<Slider x:Name="Slider" Grid.Column="0" Grid.Row="1" Grid.ColumnSpan="2"
MouseLeftButtonDown="MouseClicked" MouseLeftButtonUp="MouseReleased"
ValueChanged="Slider_ValueChanged" Height="30" Width="484" ></Slider>
Code behind for slider events:
private void Slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
Audio.Pause();
Audio.Position = TimeSpan.FromSeconds(Slider.Value);
Audio.Play();
}
private void MouseClicked(object sender, MouseButtonEventArgs e)
{
Audio.Pause();
Audio.Position = TimeSpan.FromSeconds(Slider.Value);
}
private void MouseReleased(object sender, MouseButtonEventArgs e)
{
Audio.Play();
}
In Silverlight 3(as i know) MouseLeftButtonDown not working. You need to create own Handler in code. For example :
progress_bar.AddHandler(MouseLeftButtonDownEvent, new MouseButtonEventHandler(progress_bar_MouseLeftButtonDown), true);