I was able to make my silverlight Bing map accepts Mousclicks and converts them to Pushpins in C#. Now I want to show a text next to the PushPin as a description that appears when the mouse goes over the pin , I have no clue how to do that. What are the methods that enable me to do this thing?
This is the C# code :
public partial class MainPage : UserControl
{
private MapLayer m_PushpinLayer;
public MainPage()
{
InitializeComponent();
base.Loaded += OnLoaded;
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
base.Loaded -= OnLoaded;
m_PushpinLayer = new MapLayer();
x_Map.Children.Add(m_PushpinLayer);
x_Map.MouseClick += OnMouseClick;
}
private void AddPushpin(double latitude, double longitude)
{
Pushpin pushpin = new Pushpin();
pushpin.MouseEnter += OnMouseEnter;
pushpin.MouseLeave += OnMouseLeave;
m_PushpinLayer.AddChild(pushpin, new Location(latitude, longitude), PositionOrigin.BottomCenter);
}
private void OnMouseClick(object sender, MapMouseEventArgs e)
{
Point clickLocation = e.ViewportPoint;
Location location = x_Map.ViewportPointToLocation(clickLocation);
AddPushpin(location.Latitude, location.Longitude);
}
private void OnMouseLeave(object sender, MouseEventArgs e)
{
Pushpin pushpin = sender as Pushpin;
// remove the pushpin transform when mouse leaves
pushpin.RenderTransform = null;
}
private void OnMouseEnter(object sender, MouseEventArgs e)
{
Pushpin pushpin = sender as Pushpin;
// scaling will shrink (less than 1) or enlarge (greater than 1) source element
ScaleTransform st = new ScaleTransform();
st.ScaleX = 1.4;
st.ScaleY = 1.4;
// set center of scaling to center of pushpin
st.CenterX = (pushpin as FrameworkElement).Height / 2;
st.CenterY = (pushpin as FrameworkElement).Height / 2;
pushpin.RenderTransform = st;
}
}
You have 2 ways to go:
(1) Create any UIElement to pass into PushPinLayer.AddChild. The AddChild method will accept and any UIElement, such as this Grid containing an Image and a TextBlock:
MapLayer m_PushpinLayer = new MapLayer();
Your_Map.Children.Add(m_PushpinLayer);
Image image = new Image();
image.Source = ResourceFile.GetBitmap("Images/Pushpin.png", From.This);
TextBlock textBlock = new TextBlock();
textBlock.Text = "My Pushpin";
Grid grid = new Grid();
grid.Children.Add(image);
grid.Children.Add(textBlock);
m_PushpinLayer.AddChild(grid,
new Microsoft.Maps.MapControl.Location(42.658, -71.137),
PositionOrigin.Center);
(2) Create a native PushPin object to pass into PushpinLayer.AddChild, but first set it's Template property. Note that PushPin's are ContentControls, and have a Template property that can be set from a Resource defined in XAML:
MapLayer m_PushpinLayer = new MapLayer();
Your_Map.Children.Add(m_PushpinLayer);
Pushpin pushpin = new Pushpin();
pushpin.Template = Application.Current.Resources["PushPinTemplate"]
as (ControlTemplate);
m_PushpinLayer.AddChild(pushpin,
new Microsoft.Maps.MapControl.Location(42.658, -71.137),
PositionOrigin.Center);
...
<ResourceDictionary
xmlns="http://schemas.microsoft.com/client/2007"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
<ControlTemplate x:Key="PushPinTemplate">
<Grid>
<Image Source="Images/Pushpin.png" />
<TextBlock Text="My Pushpin" />
</Grid>
</ControlTemplate>
</ResourceDictionary>
Good luck,
Jim McCurdy
Face To Face Software, and YinYangMoney
Related
I have a simple custom tree view component:
public partial class ThemesTreeView: UserControl, IThemesTreeView {
public delegate void ThemeSelected(ThemeModel theme);
public event ThemeSelected OnThemeSelection;
public delegate void ThemeDoubleClick(ThemeModel theme);
public event ThemeDoubleClick OnThemeDoubleClick;
public ThemesTreeView() {
InitializeComponent();
}
private void UserControl_Loaded(object sender, RoutedEventArgs e) {
var caseCovers = GetTreeViewItem((Int32) ThemeType.CaseCover, "1", "Case Covers", "album_cover.png");
var musics = GetTreeViewItem((Int32) ThemeType.Music, "1", "Music", "music_run.png");
var movies = GetTreeViewItem((Int32) ThemeType.Video, "1", "Scenic Video Inserts", "video.png");
tvThemes.Items.Add(caseCovers);
tvThemes.Items.Add(musics);
tvThemes.Items.Add(movies);
}
private ThemesTreeViewItem GetTreeViewItem(Int32 tag, String uid, String text, String imagePath) {
ThemesTreeViewItem item = new ThemesTreeViewItem();
item.Uid = uid;
item.Tag = tag;
item.IsExpanded = false;
// create stack panel
StackPanel stack = new StackPanel();
stack.Orientation = Orientation.Horizontal;
// create Image
Image image = new Image();
image.Source = new BitmapImage(new Uri("pack://application:,,/images/" + imagePath));
image.Width = 16;
image.Height = 16;
// Label
Label lbl = new Label();
lbl.Content = text;
// Add into stack
stack.Children.Add(image);
stack.Children.Add(lbl);
// assign stack to header
item.Header = stack;
return item;
}
}
}
I have skipped some code for downloading and filling subnodes. When user clicks on a node then subnodes are downloaded and addded to treeview. But the problem is there is no arrow for expand/collapse until nodes will be added. How to show arrow always?
Make a copy of the treeviewitem Style. Find Part of the treenode and correct the Style of the Node similar to the state of treenode with subnodes.
here description of styling for treeviewite-controltemplate
I am creating dynamic images on canvas . T want to translate them and rotate them on button click . Translating working fine but when I rotating it its gives error like this
Additional information:
Unable to cast object of type
'Windows.UI.Xaml.Media.TranslateTransform'
to type
'Windows.UI.Xaml.Media.RotateTransform'.
Here is my code
Image i = new Image(); // Global variable for selecting
private void btn_Click(object sender, RoutedEventArgs e) // For creating images
{
int i = 0;
Image image = new Image();
string url = "ms-appx:///Assets/1.png";
BitmapImage bm = new BitmapImage();
bm.UriSource = new Uri(url, UriKind.Absolute);
image.Source = bm;
image.Height = Double.NaN;
image.Width = Double.NaN;
image.ManipulationMode = ManipulationModes.TranslateX | ManipulationModes.TranslateY | ManipulationModes.Rotate;
image.RenderTransform = new TranslateTransform();
image.Name = "img" + i;
image.Tapped += select;
image.ManipulationDelta += DragableItem_ManipulationDelta;
DrawCanvas.Children.Add(image);
i++;
}
private void select(object sender, TappedRoutedEventArgs e) // selecting of image
{
i = (Image)sender;
}
private void rotate_Click(object sender, RoutedEventArgs e) //rotating
{
if (i != null)
{
var translate = (RotateTransform)i.RenderTransform;
translate.CenterY = 0;
translate.CenterX = 0;
translate.Angle = 45;
i.RenderTransform = translate;
}
}
void DragableItem_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e) // translating code
{
var name = (Image)sender;
var translate = (TranslateTransform)name.RenderTransform;
translate.X += e.Delta.Translation.X;
translate.Y += e.Delta.Translation.Y;
}
need help stuck here for a long time ??
You are setting your RenderTransform to a TranslateTransform and then trying to cast it to a RotateTransform (as the error states). You should probably use a CompositeTransform instead or use a TransformGroup with both of the transform types in it.
I have a TextBlock. I want to draw inside it (within its current visual boundaries). I need DrawingContext for it.
How do I get DrawingContext?
(MSDN says that any FrameworkElement is descendant from Visual and the Visual provides support for rendering.. But I cant quite find how exactly)
Please note - this code will be called several time a second. I am looking for the most efficient solution (this is why I took on the DrawingContext in first place).
what I did: I wrote my own adorner, adorned the textblock, used OnRender to get DrawingContext, I am writing text directly to the adorner and invalidating Visual at each change.
The boost in performance (measured carefully with Ants profiler) is 4.5 times better than writing text directly to the text block and even more so than binding string property.
Why not overlay the TextBlock on a Canvas and draw to the Canvas ?
XAML
<Grid>
<Canvas Background='Orange'
x:Name='drawingCanvas'
Width='{Binding ActualWidth, ElementName=textblock1, Mode=OneWay}'
Height='{Binding ActualHeight, ElementName=textblock1, Mode=OneWay}' />
<TextBlock Text='Example'
x:Name='textblock1'
HorizontalAlignment='Center'
VerticalAlignment='Center'
FontSize='40' />
</Grid>
CODE
public MainWindow() {
InitializeComponent();
this.Loaded += MainWindow_Loaded;
_timer.Interval = TimeSpan.FromMilliseconds(100);
_timer.Start();
_timer.Tick += _timer_Tick;
}
private void _timer_Tick(object sender, EventArgs e) {
var newX = _bezierSeg.Point1.X + .1;
_bezierSeg.Point1 = new Point(Math.Sin(newX) * 12, 0);
}
private DispatcherTimer _timer = new DispatcherTimer();
private BezierSegment _bezierSeg = new BezierSegment();
private void MainWindow_Loaded(object sender, RoutedEventArgs e) {
var arcPath = new Path();
var figure = new PathFigure();
figure.StartPoint = new Point(0, 0);
var Point1 = new Point(textblock1.ActualHeight, 0);
var Point2 = new Point(textblock1.ActualWidth - 30, textblock1.ActualHeight - 20);
var Point3 = new Point(textblock1.ActualWidth, textblock1.ActualHeight);
_bezierSeg.Point1 = Point1;
_bezierSeg.Point2 = Point2;
_bezierSeg.Point3 = Point3;
var myPathSegmentCollection = new PathSegmentCollection();
myPathSegmentCollection.Add(_bezierSeg);
figure.Segments = myPathSegmentCollection;
var pathCollection = new PathFigureCollection();
pathCollection.Add(figure);
var pathGeometry = new PathGeometry();
pathGeometry.Figures = pathCollection;
arcPath.Stroke = new SolidColorBrush(Colors.Red);
arcPath.Fill = new SolidColorBrush(Colors.Yellow);
arcPath.StrokeThickness = 2;
arcPath.Data = pathGeometry;
drawingCanvas.Children.Add(arcPath);
}
What I am looking for is for the user to
1. click on the canvas
2. a new label show up and the user can enter text.
3. When the user clicks elsewhere or hit enter the labels is finished editing.
This is what I have so far...
private void DrawingCanvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) {
var canvas = (Canvas)sender;
var point = e.GetPosition(canvas);
Label lbl = new Label();
lbl.Content = "start typing";
//lbl.Left = location.X;
//lbl.Top = location.Y;
//lbl.Focus = Boolean.TrueString;
canvas.Children.Add(lbl);
}
Any help would be greatly appreciated, thanks!
Try like this
<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="350" Width="525">
<Canvas x:Name="cnvs" PreviewMouseLeftButtonUp="cnvs_MouseLeftButtonUp" Background="Transparent"></Canvas>
private void cnvs_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
var canvas = (Canvas)sender;
var point = e.GetPosition(canvas);
TextBox txtBox = new TextBox() {Width=80,AcceptsReturn=false };
canvas.Children.Add(txtBox);
Canvas.SetLeft(txtBox, point.X);
Canvas.SetTop(txtBox, point.Y);
txtBox.Focus();
}
I hope this will help.
UPDaTE:
var canvas = (Canvas)sender;
var point = e.GetPosition(canvas);
TextBox txtBox = new TextBox() {AcceptsReturn=false ,BorderThickness=new Thickness(0)};
Binding b = new Binding("Text") { RelativeSource = new RelativeSource(RelativeSourceMode.Self) };
txtBox.SetBinding(TextBox.WidthProperty, b);
canvas.Children.Add(txtBox);
Canvas.SetLeft(txtBox, point.X);
Canvas.SetTop(txtBox, point.Y);
txtBox.Focus();
Try setting the textbox width to Double.NaN. This will give you an "Auto" width. To get rid of the border, set the textbox's borderthickness to 0. See below:
private void cnvs_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
var canvas = (Canvas)sender;
var point = e.GetPosition(canvas);
var txtBox = new TextBox() { Width=Double.NaN, AcceptsReturn=false }; // auto width
txtBox.BorderThickness = new Thickness(0); // no border
canvas.Children.Add(txtBox);
Canvas.SetLeft(txtBox, point.X);
Canvas.SetTop(txtBox, point.Y);
txtBox.Focus();
}
I m using MouseDragElementBehavior in my WP7 application to drag an image down the canvas. I m able to get the coordinates (X,Y positions) after the image dragging. But I want to retain the same image position after tombstoning also.
private void MouseDragElementBehavior_Dragging(object sender, MouseEventArgs e)
{
Point currentPos = e.GetPosition(image1);
if (currentPos.X < 190)
{
double targetOffset = 700;
DoubleAnimation animation = new DoubleAnimation();
animation.EasingFunction = new CircleEase();
animation.Duration = new Duration(new TimeSpan(0, 0, 10));
animation.From = TextScroll.AnimatableOffset;
animation.To = targetOffset;
Storyboard.SetTarget(animation, TextScroll);
Storyboard.SetTargetProperty(animation, new PropertyPath("(AnimatableScrollViewer.AnimatableOffset)"));
Storyboard storyboard = new Storyboard();
storyboard.Children.Add(animation);
storyboard.Begin();
}
App app = (App)Application.Current;
app.current_X = currentPos.X.ToString();
app.current_Y = currentPos.Y.ToString();
TextScroll.AnimatableOffset = -700;
}
I have stored and retrived the values from isolated storage for tombstoning.
private void LoadSettings()
{
var settings = IsolatedStorageSettings.ApplicationSettings;
current_X = settings["Xpos"].ToString();
current_Y = settings["Ypos"].ToString();
}
private void SaveSettings()
{
var settings = IsolatedStorageSettings.ApplicationSettings;
settings.Add("Xpos", current_X);
settings.Add("Ypos",current_Y);
settings.Save();
}
Now I would like to use the values to position the image at the same coordinates as before tombstoning. I dont know how to position the image with the X and Y coordinates provided.
Here is the XAML code where I use the image.
<Canvas Margin="12,0,3,-834" Grid.Row="1">
<Image Height="800" Source="37.jpg" Stretch="Fill" Width="480" Canvas.Left="-11" x:Name="image1">
<i:Interaction.Behaviors>
<el:MouseDragElementBehavior ConstrainToParentBounds="True" Dragging="MouseDragElementBehavior_Dragging" />
</i:Interaction.Behaviors>
</Image>
</Canvas>
First, Point currentPos = e.GetPosition(image1); is getting the position of the mouse relative to the image. Maybe you want to get the position relative to the canvas instead?
Or, you can use this to get the position within the canvas:
canvas1.GetLeft(image1);
canvas1.GetTop(image1);
Then, you can set the position of something within a canvas like this:
canvas1.SetLeft(image1, x);
canvas1.SetTop(image1, y);
To do that, you would need to name your Canvas:
<Canvas x:Name="canvas1" Margin="12,0,3,-834" Grid.Row="1">