I have a method which draws lines in a canvas like this:
public void drawoncanvas(double[] coord, string fullkey)
{
myLine = new Line();
myLine.X1 = coord[0];
myLine.X2 = coord[2];
myLine.Y1 = coord[1];
myLine.Y2 = coord[3];
MainWindow.mycanvas.Children.Add(myLine);
myLine.MouseEnter += mymouse; //add MousEnter Event
myLine.MouseLeave += mymouseleave; //add MouseLeave Event
}
The MouseEnter Event then adds a DropShadowEffect to the line that triggers the event:
public void mymouse(object sender, MouseEventArgs e)
{
Line thisline = sender as Line;
thisline.Effect = new DropShadowEffect{Color = new Color { A = 255, R = 255, G = 255, B = 0 }, Direction = 320,ShadowDepth = 0, Opacity = 1};
}
This works fine. But now I want to remove this effect as soon as the mouse cursor is not anymore over the line:
public void mymouseleave(object sender, MouseEventArgs e)
{
Line thisline = sender as Line;
thisline.Effect = null; //this doesn't do anything
}
I know this is a is probably a really simple question but I couldn't find any solution so far.
EDIT:
Ok I found what causes the problem, still don't know a solution though: I don't only create the dropshadow in the MouseEnter event but also display a tootltip, so my full Code is actually:
public void drawoncanvas(double[] coord, string fullkey)
{
myLine = new Line();
myLine.Stroke = Brushes.Red;
myLine.X1 = coord[0];
myLine.X2 = coord[2];
myLine.Y1 = coord[1];
myLine.Y2 = coord[3];
myLine.Tag = fullkey;
MainWindow.mycanvas.Children.Add(myLine);
myLine.MouseEnter += mymouse;
myLine.MouseLeave += mymouseleave;
}
ToolTip tt = new ToolTip();
public void mymouse(object sender, MouseEventArgs e)
{
Line thisline = sender as Line;
string data = Convert.ToString(thisline.Tag);
string[] splitdata = data.Split('/');
tt.Content = String.Concat(splitdata[0], " -> ", splitdata[3] ,"kt -> ", splitdata[1]);
tt.StaysOpen = false;
tt.IsOpen = true; //the removing of the shadow on MouseLeave works when I comment this line out
thisline.Effect = new DropShadowEffect{Color = new Color { A = 255, R = 255, G = 255, B = 0 }, Direction = 320,ShadowDepth = 0, Opacity = 1};
}
public void mymouseleave(object sender, MouseEventArgs e)
{
Line thisline = sender as Line;
tt.IsOpen = false;
thisline.Effect = null;
}
If I simply comment out the tt.IsOpen = true; and do not display the tooltip it all works fine.....I'm really confused.
EDIT 2:
Here the XAML:
<Window x:Class="mapO1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:mapO1"
Title="mapO1" Height="600" Width="750" WindowStartupLocation="CenterScreen" SizeChanged="MainWindow_SizeChanged">
<Grid>
<Grid x:Name="mygrid">
<local:ZoomBorder x:Name="border" ClipToBounds="True" Background="Black">
<Grid Name="maingrid">
<Image Name="image1" />
<Canvas Name="mycanvas" HorizontalAlignment="Left" VerticalAlignment="Top" ClipToBounds="False"/>
</Grid>
</local:ZoomBorder>
<Button x:Name="button1" Content="Fullscreen on/off" HorizontalAlignment="Right" Height="18" Margin="0,20,50,0" VerticalAlignment="Top" Opacity="0.5" Width="108" FontWeight="Bold" Click="button1_Click"/>
<ComboBox x:Name="comboBox1" Height="24" HorizontalAlignment="Left" VerticalAlignment="Top" Width="150" Margin="10,20,0,0" Opacity="0.5" FontWeight="Bold" Text="Select Period" SelectionChanged="comboBox1_SelectionChanged"/>
<ComboBox x:Name="comboBox2" Height="24" HorizontalAlignment="Left" VerticalAlignment="Top" Width="150" Margin="10,60,0,0" FontWeight="Bold" Opacity="0.5" Text="Select Stream" DropDownClosed="comboBox2_DropDownClosed"/>
</Grid>
</Grid>
</Window>
Related
I am creating UWP app, and I maked external arrow "marker" of selected item in listview...
Like this:
I have managed to achieve this with next code:
var current = lvMain.Items.FirstOrDefault(a => (a as MyModel).Selected) as MyModel;
ListViewItem selected = lvMain.ContainerFromItem(current) as ListViewItem;
GeneralTransform generalTransform1 = gvEpg.TransformToVisual(selected);
Point currentPoint = generalTransform1.TransformPoint(new Point());
In Scroll change event I am calling this and set the arrow position by the Point of my item. And this is working.
But, I want to simplified this. Is there any kind of binding or something like that, that would make arrow always follow the item?
Here's the sample.
XAML MainPage:
<Page.Resources>
<DataTemplate x:Key="DataTemplate">
<Canvas Height="80" Width="200">
<TextBlock Text="{Binding}"/>
</Canvas>
</DataTemplate>
</Page.Resources>
<StackPanel Orientation="Horizontal">
<ListView x:Name="ListView" Width="400"
SelectionChanged="ListView_OnSelectionChanged"
ItemTemplate="{StaticResource DataTemplate}"/>
<Canvas x:Name="ParentCanvas">
<Image x:Name="Arrow"
Stretch="UniformToFill" Width="200" Height="80"
Source="Assets/Red_Left_Arrow.png"/>
</Canvas>
</StackPanel>
Code behind:
private readonly List<string> _names = new List<string>();
private Visual _rectangleVisual;
private Visual _parentVisual;
public MainPage()
{
InitializeComponent();
Loaded += MainPage_Loaded;
}
private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
for (int i = 0; i < 32; i++)
{
_names.Add("item " + i);
}
ListView.ItemsSource = _names;
_parentVisual = ElementCompositionPreview.GetElementVisual(ParentCanvas);
_rectangleVisual = ElementCompositionPreview.GetElementVisual(Arrow);
var border = VisualTreeHelper.GetChild(ListView, 0) as Border;
var scrollViewer = border.Child as ScrollViewer;
var scrollerProperties = ElementCompositionPreview.GetScrollViewerManipulationPropertySet(scrollViewer);
var offsetExpressionAnimation = _rectangleVisual.Compositor.CreateExpressionAnimation("Scroller.Translation.Y");
offsetExpressionAnimation.SetReferenceParameter("Scroller", scrollerProperties);
_rectangleVisual.StartAnimation("Offset.Y", offsetExpressionAnimation);
}
private void ListView_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
var listViewItem = ListView.ContainerFromItem(ListView.SelectedItem) as ListViewItem;
var listItemVisual = ElementCompositionPreview.GetElementVisual(listViewItem);
_parentVisual.Offset = new Vector3(_parentVisual.Offset.X, listItemVisual.Offset.Y, 0);
}
Looks like what you asked for:
I'm trying to make it so when the user clicks on a spot in my canvas, a popup is displayed that allows the user to enter two separate pieces of data. So I need two textblocks and then a way to save the data entered into some variables in the code behind. I've been looking at different tutorials and it's easy making a window with input texblocks. Just not sure how to do it with popups. The addNode_MouseDown method is where I tried adding the popup, since the information entered is going to be about the circle that the user makes when they click on the canvas. Any help would be appreciated.
Here's my code at the moment:
XAML:
<Window x:Class="CanvasStuff.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Main Window" Height="410" Width="869">
<Grid Height="387">
<Label Content="Image" Height="32" HorizontalAlignment="Left" Margin="11,10,0,0"
Name="selectedFileName" VerticalAlignment="Top" Width="137"
Background="LightGray" BorderBrush="Gray" BorderThickness="1"/>
<Button Content="Browse File" Height="34" HorizontalAlignment="Left" Margin="154,6,0,0"
Name="BrowseButton" VerticalAlignment="Top" Width="119"
Foreground="Maroon" FontSize="16" FontFamily="Georgia" Click="BrowseButton_Click" />
<Button Content="Input Range and Heading" Height="34" HorizontalAlignment="Left" Margin="279,6,0,0"
Name="InputRangeBearing" VerticalAlignment="Top" Width="191"
Foreground="Maroon" FontSize="16" FontFamily="Georgia" Click="InputButton_Click" />
<Canvas Margin="0,45,2,8" x:Name="canvas1" MouseDown= "addNode_MouseDown">
</Canvas>
</Grid>
</Window>
Code behind:
namespace CanvasStuff
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
}
private void BrowseButton_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog dlg = new OpenFileDialog();
dlg.InitialDirectory = "c:\\";
dlg.Filter = "Image files (*.jpg)|*.jpg|All Files (*.*)|*.*";
dlg.RestoreDirectory = true;
if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
string selectedFileName = dlg.FileName;
ImageBrush brush = new ImageBrush();
brush.ImageSource = new BitmapImage(new Uri(selectedFileName));
canvas1.Background = brush;
BitmapImage bitmap = new BitmapImage();
}
}
private void InputButton_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("Please click on known object to enter range and heading of that object.");
}
private void addNode_MouseDown(object sender, MouseButtonEventArgs e)
{
Point currentPoint = new Point();
if (e.ButtonState == MouseButtonState.Pressed)
currentPoint = e.GetPosition(this);
Ellipse ellipse = new Ellipse();
SolidColorBrush mySolidColorBrush = new SolidColorBrush();
mySolidColorBrush.Color = Color.FromArgb(255, 255, 255, 0);
ellipse.Fill = mySolidColorBrush;
ellipse.Width = 10;
ellipse.Height = 10;
Canvas.SetLeft(ellipse, e.GetPosition(canvas1).X);
Canvas.SetTop(ellipse, e.GetPosition(canvas1).Y);
canvas1.Children.Add(ellipse);
}
}
}
Did you try using the PopUp window?
XAML:
<Popup Name="errMsg" StaysOpen="False">
<TextBox/>
</Popup>
in your code behind:
errMsg.IsOpen = true;
Or you could either create fully using your code:
WPF popup window
Reference:
Popup a User Control
Cropping the image is not working properly. Where I'm wrong?
My Xaml :
<Grid x:Name="Gridimage1">
<Image Name="image1" Grid.Column="0" Height="317" HorizontalAlignment="Left" Margin="20,67,0,0" Stretch="Fill" VerticalAlignment="Top" Width="331"></Image>
<Canvas x:Name="BackPanel">
<Rectangle x:Name="selectionRectangle" Stroke="LightBlue" Fill="#220000FF" Visibility="Collapsed" />
</Canvas>
</Grid>
<Button Content=">>" Height="23" HorizontalAlignment="Left" Margin="357,201,0,0" Name="Go" VerticalAlignment="Top" Width="41" Click="Go_Click" FontWeight="Bold" Visibility="Hidden" />
<Image Grid.Column="1" Height="317" HorizontalAlignment="Left" Margin="408,67,0,0" Name="image2" Stretch="Fill" VerticalAlignment="Top" Width="331" />
C# :
private bool isDragging = false;
private Point anchorPoint = new Point();
public MainWindow()
{
InitializeComponent();
Gridimage1.MouseLeftButtonDown += new MouseButtonEventHandler(image1_MouseLeftButtonDown);
Gridimage1.MouseMove += new MouseEventHandler(image1_MouseMove);
Gridimage1.MouseLeftButtonUp += new MouseButtonEventHandler(image1_MouseLeftButtonUp);
Go.IsEnabled = false;
image2.Source = null;
}
private void Go_Click(object sender, RoutedEventArgs e)
{
if (image1.Source != null)
{
Rect rect1 = new Rect(Canvas.GetLeft(selectionRectangle), Canvas.GetTop(selectionRectangle), selectionRectangle.Width, selectionRectangle.Height);
System.Windows.Int32Rect rcFrom = new System.Windows.Int32Rect();
rcFrom.X = (int)((rect1.X) * (image1.Source.Width) /(image1.Width));
rcFrom.Y = (int)((rect1.Y) *(image1.Source.Height) / (image1.Height));
rcFrom.Width = (int)((rect1.Width) * (image1.Source.Width) /(image1.Width));
rcFrom.Height = (int)((rect1.Height) * (image1.Source.Height) /(image1.Height));
BitmapSource bs = new CroppedBitmap(image1.Source as BitmapSource, rcFrom);
image2.Source = bs;
}
}
#region "Mouse events"
private void image1_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (isDragging == false)
{
anchorPoint.X = e.GetPosition(BackPanel).X;
anchorPoint.Y = e.GetPosition(BackPanel).Y;
isDragging = true;
}
}
private void image1_MouseMove(object sender, MouseEventArgs e)
{
if (isDragging)
{
double x = e.GetPosition(BackPanel).X;
double y = e.GetPosition(BackPanel).Y;
selectionRectangle.SetValue(Canvas.LeftProperty, Math.Min(x, anchorPoint.X));
selectionRectangle.SetValue(Canvas.TopProperty, Math.Min(y, anchorPoint.Y));
selectionRectangle.Width = Math.Abs(x - anchorPoint.X);
selectionRectangle.Height = Math.Abs(y - anchorPoint.Y);
if (selectionRectangle.Visibility != Visibility.Visible)
selectionRectangle.Visibility = Visibility.Visible;
}
}
private void image1_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (isDragging)
{
isDragging = false;
if(selectionRectangle.Width >0)
{
Go.Visibility = System.Windows.Visibility.Visible;
Go.IsEnabled = true;
}
if (selectionRectangle.Visibility != Visibility.Visible)
selectionRectangle.Visibility = Visibility.Visible;
}
}
private void RestRect()
{
selectionRectangle.Visibility = Visibility.Collapsed;
isDragging = false;
}
#endregion
It is cropping the wrong part.
The Margin property was not set properly to the Canvas control. It should be the same as Image control's margin properly value. If we don't set Margin to Canvas, It will take the full window size.
Xaml
<Grid x:Name="Gridimage1" Margin="0,0,411,100">
<Image Name="image1" Grid.Column="0" Height="317" HorizontalAlignment="Left" Margin="20,67,0,0" Stretch="Fill" VerticalAlignment="Top" Width="331">
</Image>
<Canvas x:Name="BackPanel" Margin="20,67,0,0">
<Rectangle x:Name="selectionRectangle" Stroke="LightBlue" Fill="#220000FF" Visibility="Collapsed" />
</Canvas>
</Grid>
<Grid x:Name="other">
<Button Content=">>" Height="23" HorizontalAlignment="Left" Margin="341,152,0,0" Name="Go" VerticalAlignment="Top" Width="41" Click="Go_Click" FontWeight="Bold" />
<Image Height="317" HorizontalAlignment="Left" Margin="403,10,-217,-7" Name="image2" Stretch="Fill" VerticalAlignment="Top" Width="331" />
</Grid>
</Grid>
I have a WPF app that I'm testing which loads a XML and visualizes it in a usercontrol. Now the issue I'm having is that every time I load my user control the HorizontalAlignment is okay, but the VerticalAlignment doesn't adept to the height size of the usercontrol.
Anyone has an idea how to solve this?
MainWindow.xaml
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:UserControls="clr-namespace:RackBuildingTesT.UserControls" x:Class="RackBuildingTesT.MainWindow"
Title="MainWindow" Height="578" Width="758" SizeChanged="Window_SizeChanged_1">
<Grid>
<DockPanel HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Border DockPanel.Dock="Top" BorderBrush="Black" BorderThickness="1">
<Grid>
<Label Content="Welke rack laden" HorizontalAlignment="Left" VerticalAlignment="Top"/>
<ComboBox x:Name="RackChooser" HorizontalAlignment="Left" Margin="100,0,0,0" VerticalAlignment="Top" Width="120" SelectionChanged="RackChooser_SelectionChanged"/>
</Grid>
</Border>
<Border DockPanel.Dock="Top" BorderBrush="Black" BorderThickness="1">
<Grid x:Name="RackGrid" Margin="0,0,0,0">
</Grid>
</Border>
</DockPanel>
</Grid>
MainWindow.xaml.cs
public MainWindow()
{
InitializeComponent();
LoadRackCombo();
}
private void LoadRackCombo()
{
var files = Directory.GetFiles(Properties.Settings.Default.FilePathXMLRack);
foreach (var item in files)
{
RackChooser.Items.Add(item);
}
}
private void RackChooser_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
this.RackGrid.Children.Clear();
this.Cursor = Cursors.Wait;
if (RackChooser.SelectedIndex == -1)
MessageBox.Show("Select a rack");
else
{
string rackFile = Convert.ToString(RackChooser.Items[RackChooser.SelectedIndex]);
UserControls.RackBuilder r = new UserControls.RackBuilder();
RackGrid.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
RackGrid.VerticalAlignment = System.Windows.VerticalAlignment.Stretch;
r.Width = RackGrid.Width;
r.Height = RackGrid.Height;
var _r = TRack.CreateFromXMLFile(rackFile, null);
r.set_Rack(_r);
RackGrid.Children.Add(r);
}
this.Cursor = Cursors.Arrow;
}
private void Window_SizeChanged_1(object sender, SizeChangedEventArgs e)
{
RackGrid.Width = this.Width;
RackGrid.Height = this.Height;
}
RackBuilder.xaml.cs (xaml page is standard WPF usercontrol)
public RackBuilder()
{
InitializeComponent();
}
public TRack fRack { get; set; }
public void set_Rack(TRack value)
{
this.fRack = value;
this.InvalidateVisual();
}
protected override void OnRender(DrawingContext drawingContext)
{
if (this.fRack != null)
{
var xScale = this.Width / this.fRack.Size.Width;
var yScale = this.Height / this.fRack.Size.Height;
var smallest = 0.0;
if (xScale < yScale)
smallest = xScale;
else
smallest = yScale;
foreach (var hole in this.fRack.HolePositions)
{
drawingContext.DrawEllipse(Brushes.Aquamarine, null, new Point(hole.Position.X * xScale, hole.Position.Y * yScale),
hole.Diameter * smallest * 0.5, hole.Diameter * smallest * 0.5);
}
}
}
Result
Instead of adding your Control to a Grid, use the ContentControl and add it to its Content-Property.
It also stretches its child automatically.
I fixed it with putting the MainWindow SizeToContent to WidthAndHeight.
I am trying to create Rectangle programmaticallyin silverlight as fallows.
C#
private Boolean Working = false;
const int scale = 4;
const int size = 50;
Int32[] data = new Int32[size];
Rectangle[] lines = new Rectangle[size];
private void button1_Click(object sender, RoutedEventArgs e)
{
canvas1.Children.Clear();
for (int i = 0; i < data.Length; i++)
{
data[i] = i;
lines[i] = new Rectangle()
{
Height=i*scale,
Width = 10,
StrokeThickness=5,
Stroke = new SolidColorBrush(Colors.Red),
Name=i.ToString(),
};
canvas1.Children.Add(lines[i]);
}
}
Now the problem is that all the rectangle are created with the same height and width?.
XAML
<UserControl x:Class="SilverlightApplication1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="500" d:DesignWidth="500">
<Canvas x:Name="canvas2" Background="White">
<Canvas x:Name="canvas1" Background="White"></Canvas>
<Button Content=" Generate" Height="38" Name="button1" Width="75" Click="button1_Click" Margin="0,352,245,24" HorizontalAlignment="Right" Canvas.Left="12" Canvas.Top="85" />
<Button Content="Shuffle" Height="38" HorizontalAlignment="Left" Name="button2" Margin="12,352,0,24" Click="button2_Click_1" Canvas.Left="81" Canvas.Top="85" Width="71" />
<Button Canvas.Left="181" Canvas.Top="437" Content="Bubble Sort" Height="38" Name="button3" Width="109" Click="button3_Click" />
</Canvas>
</UserControl>
Screenshot
Actually, everything works fine. All rectangles have different height. But you forget to move them, so they start overlapping. Change a little code and you'll see:
lines[i] = new Rectangle()
{
Height = i * scale,
Width = 10,
StrokeThickness = 5,
Stroke = new SolidColorBrush(Colors.Red),
Name = i.ToString(),
};
lines[i].Margin = new Thickness(11 * i, 0, 0, 0);
Result