I declared a UniformGrid in my XAML file:
<UniformGrid Rows="8" Columns="8" Background="OliveDrab"
Name="board" Width="400" Height="400"/>
Then, I would like to programmatically add Rectangle children to it, and attach an event handler to each of them:
public MainWindow()
{
InitializeComponent();
createGrid();
}
private void createGrid()
{
SolidColorBrush scb = Brushes.Olive;
for (int i = 0; i < 64; i++)
{
Rectangle r = new Rectangle();
r.Stroke = scb;
r.MouseLeftButtonDown += Rectangle_MouseLeftButtonDown;
board.Children.Add(r);
}
}
private void Rectangle_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Console.WriteLine("Rectangle_MouseLeftButtonDown");
}
But when I run the app and click on a Rectangle, the Rectangle_MouseLeftButtonDown is never called, unless I set a Fill property:
private void createGrid()
{
SolidColorBrush scb = Brushes.Olive;
SolidColorBrush whiteScb = Brushes.White;
for (int i = 0; i < 64; i++)
{
Rectangle r = new Rectangle();
r.Stroke = scb;
r.Fill = whiteScb;
r.MouseLeftButtonDown += Rectangle_MouseLeftButtonDown;
board.Children.Add(r);
}
}
Then and only then, the event is triggered.
So my question is: why must the Fill property of a Rectangle be set in order to make the event handler work?
Thanks.
Edit: as King King pointed, it looks like transparent windows don't send mouse events. More info: 'Transparent Windows in WPF' on msdn.
This is because you don't set the Fill property, the Rectangle's background will be transparent, and transparent controls are also "transparent" to mouse click. Hit testing goes straight to the first non-transparent control under it.
If you want to get a transparent rectangle which can be clicked then try
r.Fill = new SolidColorBrush(Colors.Black);
r.Opacity = 0;
However, you can set the Rectangle's Fill property to Transparent and it will pass on hit test and send the needed mouse events while Rectangle remains transparent.
Related
How do I create a border made of picture boxes, I'm trying to make a snake game and I want to first make a border for the playing area, using picture boxes, so far I have used a while loop to make the top row but I feel there would be a better way to make the whole thing, I heard a helper function may help but I'm not sure how to go about that either
int i = 1;
public Snake()
{
InitializeComponent();
}
private void Snake_Load(object sender, EventArgs e)
{
while (i < 404)
{
var picture = new PictureBox
{
Name = "pictureBox",
Size = new Size(20, 20),
Location = new Point(i, 0),
BackColor = Color.FromArgb(0,0,0),
};
this.Controls.Add(picture);
i += 20;
}
}
I am working on a simple Windows Forms application which consists of a Panel where I draw graphics with Graphic. Let's say, my panel is now of size 300x300 but the content inside is 500x500. Obviously, I need to add scrollbars to the Panel.
My code so far:
public CircuitControl()
{
// Initialize empty list of circuit objects
CircuitObjects = new List<CircuitObject>();
drawingAreaPanel.AutoScroll = true;
drawingAreaPanel.VerticalScroll.Enabled = true;
drawingAreaPanel.VerticalScroll.Visible = true;
drawingAreaPanel.HorizontalScroll.Enabled = true;
drawingAreaPanel.MaximumSize = new Size(300, 300);
drawingAreaPanel.Size = new Size(600, 600);
}
But none of these codes create actually a scroll bar. My question is: Where and how do I set the size of the Panel where I actually drew? I think this is the part which is missing. Thanks.
The scrollbars won't show up until there's actually something in the Panel that you can't see all of.
Try placing a larger control, such as a PictureBox, inside the Panel, and setting the PictureBox's initial size as larger than the Panel.
Just add:
drawingAreaPanel.AutoScroll = true;
And it will be done automatically.
€dit: Don't forget to set the anchors in order to get the scrollbars.
A clean and simple approach is to set AutoScrollMinSize. This shows the scrollbars (or just one if you leave the other value at 0).
Now drawing through the graphics object will not be scrolled automatically.
This can be easily achieved with a transformation matrix, which is set before painting and translates the drawing by the scroll offset.
A pretty example: (this flickers of course without further optimizations)
private void button1_Click(object sender, EventArgs e)
{
using(Form frm = new Form())
{
Panel pnl = new Panel();
pnl.Paint += delegate (Object snd, PaintEventArgs e2) {
Matrix mtx = new Matrix();
mtx.Translate(pnl.AutoScrollPosition.X, pnl.AutoScrollPosition.Y);
e2.Graphics.Transform = mtx;
e2.Graphics.Clear(Color.Black);
for(int i=0; i <= 125; i++)
for(int j=0; j <= 125; j++)
using(Brush b = new SolidBrush(Color.FromArgb(255, 255-i*2, j*2, (i*j) % 255)))
e2.Graphics.FillRectangle(b, new Rectangle(5+j*20, 5+i*20, 20, 20));
};
pnl.AutoScrollMinSize = new Size(126*20+10, 126*20+10);
pnl.Dock = DockStyle.Fill;
frm.Controls.Add(pnl);
frm.Padding = new Padding(25);
frm.ShowDialog(this);
}
}
I want to erase image loaded on canvas on mouse move and display the background image in wp7.
in C# MakeTransparent method is available.
But in windows phone no such method is available.
what to do ?
Canvas.Opacity = 0; //This will make the control transparent
Also you can use .Opacity function almost every visual user control (Image, Grid, Lists etc.)
Cleverly, you can use canvas_MouseMove event for an eraser effect.
Just subscribe to canvas mousemove event like in see the example below
//Canvas MouseMove Event
private void Canvas_MouseMove_1(object sender, System.Windows.Input.MouseEventArgs e)
{
currentPoint = e.GetPosition(this.canvas);
//Initialize line according to currentpoint position.
Line line = new Line() { X1 = currentPoint.X, Y1 = currentPoint.Y, X2 = oldPoint.X, Y2 = oldPoint.Y };
line.StrokeDashCap = PenLineCap.Round;
line.StrokeEndLineCap = PenLineCap.Round;
line.StrokeLineJoin = PenLineJoin.Round;
line.StrokeThickness = 10;
line.Stroke = new SolidColorBrush(Colors.White) ;
////////////////////////////////
//Set color & thickness of line.
//Line add in canvas children to draw image & assign oldpoint.
this.canvas.Children.Add(line);
oldPoint = currentPoint;
}
Not too sure with it but still, I hope it helps.
I'm using an adorner layer to make a grid (like, boxes across the entire screen) across my grid (WPF grid).
I want this to be shown ONLY when a checkbox is marked. However, when I bind the "IsEnabled" property, nothing happens. Even if I set the IsEnabled to false, the grid overlay is still shown!
This is how I do from my mainWindow.xaml, note the IsEnabled is set to false, but it is still showing up:
<Grid>
<!--Adornerdecorator is made to make sure the adorner is in the background, and not the foreground-->
<AdornerDecorator>
<View:GridWithRulerxaml IsEnabled="False" />
</AdornerDecorator>
<ItemsControl ItemsSource="{Binding Classes}"/>
<ItemsControl ItemsSource="{Binding Edges}"/>
</Grid>
this is the adorner usercontrol:
namespace UMLDesigner.View
{
/// <summary>
/// Interaction logic for GridWithRulerxaml.xaml
/// </summary>
public partial class GridWithRulerxaml : UserControl
{
public GridWithRulerxaml()
{
InitializeComponent();
//Loaded event is necessary as Adorner is null until control is shown.
Loaded += GridWithRulerxaml_Loaded;
}
void GridWithRulerxaml_Loaded(object sender, RoutedEventArgs e)
{
var adornerLayer = AdornerLayer.GetAdornerLayer(this);
var rulerAdorner = new AlignmentAdorner(this);
adornerLayer.Add(rulerAdorner);
}
}
}
And finally the adorner itself:
namespace UMLDesigner.Utilities
{
public class AlignmentAdorner : Adorner
{
private FrameworkElement element;
public AlignmentAdorner(UIElement el)
: base(el)
{
element = el as FrameworkElement;
}
protected override void OnRender(System.Windows.Media.DrawingContext drawingContext)
{
base.OnRender(drawingContext);
double height = element.ActualHeight;
double width = element.ActualWidth;
double linesHorizontal = height / 50;
double linesVertical = width / 50;
var pen = new Pen(Brushes.LightGray, 1) { StartLineCap = PenLineCap.Triangle, EndLineCap = PenLineCap.Triangle };
int offset = 0;
for (int i = 0; i <= linesVertical; ++i)
{
offset = offset + 50;
drawingContext.DrawLine(pen, new Point(offset, 0), new Point(offset, height));
}
offset = 0;
for (int i = 0; i <= linesHorizontal; ++i)
{
offset = offset + 50;
drawingContext.DrawLine(pen, new Point(0, offset), new Point(width, offset));
}
}
}
}
I really hope you can help me out here guys.
The IsEnabled property only enables/disables interaction with the element, and has nothing to do with the Visibility.
What you should do is set the Visibility property of the GridWithRulerxaml to Collapsed or Hidden when you want to hide it, and set it to Visible when you want it shown.
Edit: Tested it, setting the visiblity to Hidden of the GridWithRulerxaml usercontrol inside the AdornerDecorator doesn't hide the adorner.
And thinking some more about it, if this isn't what you want, it might be possible to do this with the IsEnabled property, watching for changes in it and adding/removing the adorner depending on the value.
I'm trying to set an image background in code-behind. I tried adding a background image to the button, but as soon as I hover over the button, the image disappears. To solve this, I have to write functions to override the button behavior, which is too much to do in code-behind.
I then use an alternative method, that is to add a button and an image separately to a grid cell. The issue is -- when I click on the image, the button won't trigger.
How do I make the button to have the hover and pressed effect, even when, the mouse is either hovering or presses the image on the button, but not the remaining area of the button?
Or hope someone can suggest me a better solution.Below is my code.
InitializeComponent();
Button playBtn = new Button();
playBtn.Width = 60;
playBtn.Height = 30;
Image playIcon = new Image();
playIcon.Source = new BitmapImage(new Uri(#"PATH"));
playIcon.Stretch = Stretch.Uniform;
playIcon.Height = 25;
grid1.Children.Add(playBtn);
grid1.Children.Add(playIcon);
Grid.SetColumn(playBtn, 0);
Grid.SetRow(playBtn, 0);
Grid.SetColumn(playIcon, 0);
Grid.SetColumn(playIcon, 0);
thanks for everyone input, after digging more into it, it sort of work out. What I did is add a Grid to Button.Content then add the image to the Grid. And using Opacity to add the grey out effect for IsEnable false state. Below I post my code, hope someone find it useful or improve on:
Button playBtn = new Button();
Image playIcon = new Image();
public MainWindow()
{
InitializeComponent();
Grid grid2 = new Grid();
RowDefinition grid2_row1 = new RowDefinition();
ColumnDefinition grid2_col1 = new ColumnDefinition();
grid2.RowDefinitions.Add(grid2_row1);
grid2.ColumnDefinitions.Add(grid2_col1);
playBtn.Width = 60;
playBtn.Height = 30;
playBtn.Click += playBtn_Click;
playIcon.Source = new BitmapImage(new Uri(#"pack://PATH..."));
playIcon.Stretch = Stretch.Uniform;
playIcon.Height = 25;
playBtn.Content = grid2;
grid2.Children.Add(playIcon);
grid1.Children.Add(playBtn);
Grid.SetRow(playIcon, 0);
Grid.SetColumn(playIcon, 0);
}
public void playBtn_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("Hello");
}
private void button1_Click(object sender, RoutedEventArgs e)
{
playBtn.IsEnabled = false;
playIcon.Opacity = 0.3;
}
Buttons in WPF have different states = "normal", "mouse over" and "pressed" are three.
When you create the button you are setting up it's "normal" state. You also need to set the "mouse over" state to have the same image as well.
Check the below links
http://blogs.msdn.com/b/knom/archive/2007/10/31/wpf-control-development-3-ways-to-build-an-imagebutton.aspx
http://www.hardcodet.net/2009/01/create-wpf-image-button-through-attached-properties
http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/91df562f-414c-4326-ac65-42ef301b5f8f/