I'm trying to design a button that has the DockChanged EH that knows the height & width of its paren't container (panel) and adjusts its metrics accordingly. E.g. button has text and icon, but if button width is in a panel that is too small, it will just show its icon and disable the text, etc.
Here's the method i'm trying to invoke the method with:
InnerPanel.DockChanged += HandleDockChanged;
Here's the method i'm trying to invoke the method on:
private void HandleDockChanged(EventArgs args)
{
//sorry for magic numbers
if (Parent.Height < Height || Parent.Width < Width)
{
TextLabel.Enabled = false;
InnerPanel.Width = ButtonWidth;
InnerPanel.Height = ButtonHeight;
Padding = new Padding(1);
}else
{
TextLabel.Enabled = true;
InnerPanel.Width = ButtonWidth * 2;
InnerPanel.Height = ButtonWidth * 2;
}
}
Related
I have a drag and drop interface in my Universal Windows App, where the user can add a textbox to the image, and drag and scale it around, as if it was a textbox in MSPaint, but it can be edited after it is placed, by double-tapping it.
I have implemented this as such:
textBox.LostFocus sets textBox.IsReadOnly = true;
textBox.DoubleTapped sets IsReadOnly back to false, so that it can drag around.
textBox.ManipulationDelta moves the textBox around.
Now I have the problem that the textBox has this rubberbanding effect going on, and that this blocks the manipulation event.
Is there a way to disable this? Or can I for example say when the mouse clicks (or finger or whatever), that it should start the manipulation event?
Code for a new TextBox:
private TextBox CreateManipulativeTextBox(string text)
{
var textBox = new TextBox
{
Text = text,
Background = new SolidColorBrush(Color.FromArgb(0, 0, 0, 0)),
BorderBrush = new SolidColorBrush(Color.FromArgb(128, 0, 0, 0)),
Width = 150,
Height = 50,
ManipulationMode = ManipulationModes.TranslateX | ManipulationModes.TranslateY | ManipulationModes.Scale,
RenderTransform = new CompositeTransform()
};
// Doubletap gives edit possibility, tap outside loses editability
textBox.LostFocus += TextBoxOnLostFocus;
textBox.DoubleTapped += TextBoxOnDoubleTapped;
// Add manipulation events
textBox.ManipulationStarted += OnManipulationStarted;
textBox.ManipulationDelta += OnManipulationDelta;
textBox.ManipulationCompleted += OnManipulationCompleted;
return textBox;
}
Code for focus and defocus:
private void TextBoxOnDoubleTapped(object sender, DoubleTappedRoutedEventArgs doubleTappedRoutedEventArgs)
{
(sender as TextBox).IsReadOnly = false;
}
private void TextBoxOnLostFocus(object sender, RoutedEventArgs routedEventArgs)
{
(sender as TextBox).IsReadOnly = true;
}
Code for manipulation:
private void OnManipulationStarted(object sender, ManipulationStartedRoutedEventArgs e)
{
if (sender is TextBox)
(sender as TextBox).IsReadOnly = true;
((FrameworkElement)sender).Opacity = 0.6;
}
private void OnManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
var frameworkElement = (FrameworkElement)sender;
var transform = (CompositeTransform)frameworkElement.RenderTransform;
// LEFT-RIGHT bounds
if (e.Delta.Translation.X < 0) // Going left
{
if (DrawingArea.ActualWidth / 2 + (transform.TranslateX + e.Delta.Translation.X) - frameworkElement.ActualWidth / 2 > 0)
{
// Staying inside, apply translation
transform.TranslateX += e.Delta.Translation.X;
}
else
{
// Trying to go outside, because scale sucks to work with, move image back inside
transform.TranslateX = frameworkElement.ActualWidth / 2 - DrawingArea.ActualWidth / 2;
}
}
else // Going right
{
if (DrawingArea.ActualWidth / 2 - (transform.TranslateX + e.Delta.Translation.X) +
frameworkElement.ActualWidth * (0.5 - transform.ScaleX) > 0)
{
// Staying inside, apply translation
transform.TranslateX += e.Delta.Translation.X;
}
else
{
// Trying to go outside, because scale sucks to work with, move image back inside
transform.TranslateX = frameworkElement.ActualWidth * (0.5 - transform.ScaleX) + DrawingArea.ActualWidth / 2;
}
}
// UP-DOWN bounds
if (e.Delta.Translation.Y < 0) // Going up
{
if (DrawingArea.ActualHeight / 2 + (transform.TranslateY + e.Delta.Translation.Y) - frameworkElement.ActualHeight / 2 >
0)
{
// Staying inside, apply translation
transform.TranslateY += e.Delta.Translation.Y;
}
else
{
// Trying to go outside, because scale sucks to work with, move image back inside
transform.TranslateY = frameworkElement.ActualHeight / 2 - DrawingArea.ActualHeight / 2;
}
}
else // Going down
{
if (DrawingArea.ActualHeight / 2 - (transform.TranslateY + e.Delta.Translation.Y) +
frameworkElement.ActualHeight * (0.5 - transform.ScaleY) > 0)
{
// Staying inside, apply translation
transform.TranslateY += e.Delta.Translation.Y;
}
else
{
// Trying to go outside, because scale sucks to work with, move image back inside
// transform.TranslateY = image.ActualHeight*(0.5 - transform.ScaleY) + DrawingArea.ActualHeight/2;
// Dragging down, remove image
DrawingArea.Children.Remove(frameworkElement);
}
}
// Only allow scaling when both dimensions are smaller than the drawingarea
if (frameworkElement.ActualHeight * (transform.ScaleY * e.Delta.Scale) < DrawingArea.ActualHeight &&
frameworkElement.ActualWidth * (transform.ScaleX * e.Delta.Scale) < DrawingArea.ActualWidth)
{
transform.ScaleX *= e.Delta.Scale;
transform.ScaleY *= e.Delta.Scale;
}
}
private void OnManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
{
((FrameworkElement)sender).Opacity = 1;
}
EDIT: This only happens with touch, when the mouse drags the item around it works.
C#.I have 18 buttons to select, but before I will choose a selection. How to enlarge Button with BackgroundImage when mouse point in it? It's like ToolTip, when you point the cursor it will show the Text. But in my case, it will enlarge the Button. Thanks
Button[] ButtonSelect = new Button[17];
for (i = 1; i <= 18; i++)
{
ButtonSelect[i] = new Button();
ButtonSelect[i].BackgroundImage = Properties.Resources.SelectImages[i];
}
Make the size of the Button grow larger in MouseEnter event:
Button btn = (Button)sender;
int width = btn.Size.Width;
int height = btn.Size.Height;
int larger = 10;
btn.Size = new Size(width + larger, height + larger);
Then in the MouseLeave event do the opposite by shrinking the button size.
You can hook up the events like this:
for (i = 1; i <= 18; i++)
{
ButtonSelect[i] = new Button();
ButtonSelect[i].BackgroundImage = Properties.Resources.SelectImages[i];
ButtonSelect[i].MouseEnter += new System.EventHandler(Btn_MouseEnter);
ButtonSelect[i].MouseLeave += new System.EventHandler(Btn_MouseLeave);
}
I'm using a ScrollableControl in my C# project and I'd like to know how to map the arrow keys to vertical/horizontal scrolling.
EDIT : my picture box gets the focus, and i managed to map the keys to scroll. The issue here is that when i hit an arrow key, it scrolls one time and then loses the focus to give it to a button next to the Scrollviewer. I'd like the scrollviewer NOT to lose that focus
This is my code, the second paragraph is the interesting one here.
private void drawMap(IGame game)
{
System.Windows.Forms.PictureBox pictureBox = new System.Windows.Forms.PictureBox();
pictureBox.Width = (int)Math.Sqrt((double)game.Map.grid.Count) * 50; pictureBox.Height = (int)Math.Sqrt((double)game.Map.grid.Count) * 50;
pictureBox.Paint += new System.Windows.Forms.PaintEventHandler(game.Map.afficher);
pictureBox.MouseEnter += pictureBoxFocus;
pictureBox.Click += pictureBoxFocus;
pictureBox.Click += mapClicked;
System.Windows.Forms.ScrollableControl sc = new System.Windows.Forms.ScrollableControl();
sc.Controls.Add(pictureBox);
sc.AutoScroll = true;
windowsFormsHost1.Child = sc;
}
Thank you in advance :)
PLUS : my scrolling algo is kinda dirty and don't works very well so i was wondering if there was an "easy way" to do it.
private void sc_PreviewKeyDown(object sender, System.Windows.Forms.PreviewKeyDownEventArgs e)
{
System.Windows.Forms.ScrollableControl sc = (System.Windows.Forms.ScrollableControl)sender;
switch (e.KeyValue)
{
case (int)System.Windows.Forms.Keys.Down:
sc.VerticalScroll.Value += 50;
break;
case (int)System.Windows.Forms.Keys.Up:
if(sc.VerticalScroll.Value - 50 < 0)
sc.VerticalScroll.Value = 0;
else sc.VerticalScroll.Value -= 50;
break;
case (int)System.Windows.Forms.Keys.Right:
sc.HorizontalScroll.Value += 50;
break;
case (int)System.Windows.Forms.Keys.Left:
if (sc.HorizontalScroll.Value - 50 < 0)
sc.HorizontalScroll.Value = 0;
else sc.HorizontalScroll.Value -= 50;
break;
}
windowsFormsHost1.Child.Focus();
}
I have a UIScrollView and a UIPageControl on my View in my iPhone app. I populate this Scrollview with a list of 10 buttons. The buttons all populate correctly an I can scroll through them perfectly. My question is: How do I wire up a click event to each of those buttons? Each button will perform essentially the same task (Play a sound) however the sound will be different for each of these buttons. The buttons are created programatically by the following method:
private void CreatePanels()
{
scrollView.Scrolled += ScrollViewScrolled;
int count = 10;
RectangleF scrollFrame = scrollView.Frame;
scrollFrame.Width = scrollFrame.Width * count;
scrollView.ContentSize = scrollFrame.Size;
for (int i=0; i<count; i++)
{
float h = 150.0f;
//float w = 50.0f;
float padding = 10.0f;
int n = 25;
var button = UIButton.FromType (UIButtonType.RoundedRect);
button.SetTitle (i.ToString (), UIControlState.Normal);
UIImage img = new UIImage("Images/btntest.png");
button.SetImage(img, UIControlState.Normal);
button.Frame = new RectangleF (
(padding + 40) * (i + 1) + (i * (View.Frame.Width - 100)) ,
padding,
View.Frame.Width - 100,
h);
RectangleF frame = scrollView.Frame;
PointF location = new PointF();
location.X = frame.Width * i;
frame.Location = location;
button.Frame = frame;
scrollView.AddSubview(button);
}
pageControl.Pages = count;
}
private void ScrollViewScrolled (object sender, EventArgs e)
{
double page = Math.Floor(((scrollView.ContentOffset.X - scrollView.Frame.Width) / 2) / scrollView.Frame.Width) + 1;
pageControl.CurrentPage = (int)page;
}
The CreatePanels() method is called within the ViewDidLoad() method which populates the UIScrollView.
How can I link a click event to each of these buttons? I have searched the internet a lot but to no avail.
What about wiring up an anonymous method to each click event in the for loop?
button.TouchUpInside += (s, e) =>
{
//play i.mp3
};
I'm not sure how to actually play a sound file but you could have your sound files named as i.* since that is what your buttons are named.
I'm trying to simulate an Android UI element that unfortunately doesn't exist in Windows 7 phone: ListPreference
I thought about using a Popup, that would take exactly the whole screen (to simulate a modal window).
So the popup would be made of the following elements:
Popup -> Canvas -> Border -> StackPanel -> RadioButtons
The Canvas would be fully transparent (or lightly whitish to clearly show that the element underneath aren't available)
The border would be made so it only big enough to contain all the RadioButtons
Then the StackPanel would be opaque and black.
Unfortunately, if I make the bottom canvas transparent, all children elements are also transparent. I can only make the elements more transparent.
The way transparency works is slightly different than with Android or iPhone (where it's quite easy to have a parent fully transparent, but opaque children).
Is there a way to make a parent fully transparent with the children opaque?
Or maybe someone could suggest another way to simulate a modal window.
Who knows, maybe someone even developed a ListPreference-like UIElement :)
Thank you
Here is how I ended up doing it.
It works in a similar fashion as ListPreference on Android. The constructor takes a string, an array of string and an int indicating which is the default value
When the windows is closed, the delegate Dismissed is called..
So you call it like so:
string[] choices = { "Choice 1", "Choice 2", "Choice3" };
ListPreference lp = new ListPreference("name", choices, 1);
lp.dismissed += new ListPreferences.DismissedHandler(lp_Dismissed);
the code:
public class ListPreference
{
Popup p;
string Name;
int oldValue;
public delegate void DismissedHandler(string name, bool changed, int newvalue);
public event DismissedHandler Dismissed;
public bool IsOpen
{
get
{
return p.IsOpen;
}
set
{
p.IsOpen = value;
}
}
public ListPreference(string name, Array elements, int default_value)
{
p = new Popup();
Name = name;
Dismissed = null;
oldValue = default_value;
double height = (App.Current.RootVisual as FrameworkElement).ActualHeight;
double width = (App.Current.RootVisual as FrameworkElement).ActualWidth;
p.VerticalOffset = SystemTray.IsVisible ? 32.0 : 0.0;
p.Height = height;
p.Width = width;
Canvas canvas = new Canvas();
SolidColorBrush colorBrush = new SolidColorBrush(Colors.Black);
colorBrush.Opacity = 0.75;
//Color.FromArgb(0xff, 0x8a, 0x8a, 0x8a));
canvas.Background = colorBrush;
//canvas.Opacity = 0.765;
canvas.Height = height;
canvas.Width = width;
p.Child = canvas;
Border border = new Border();
border.Width = width - 50.0 * 2.0;
border.BorderBrush = new SolidColorBrush(Colors.LightGray);
border.BorderThickness = new Thickness(5.0);
border.Background = new SolidColorBrush(Colors.Black);
canvas.Children.Add(border);
StackPanel panel2 = new StackPanel();
panel2.Orientation = System.Windows.Controls.Orientation.Vertical;
int i = 0;
foreach (string val in elements)
{
RadioButton radio1 = new RadioButton();
radio1.GroupName = "group1";
radio1.Content = val;
if (i == default_value)
radio1.IsChecked = true;
int j = i;
radio1.Click += (sender, args) => radio1_Checked(radio1, j);
i++;
panel2.Children.Add(radio1);
}
Button button1 = new Button();
button1.Background = new SolidColorBrush(Colors.Black);
button1.Foreground = new SolidColorBrush(Colors.White);
button1.Opacity = 1.0;
button1.Content = "Cancel";
button1.Margin = new Thickness(5.0);
button1.Click += new RoutedEventHandler(closeButton_Click);
panel2.Children.Add(button1);
border.Child = panel2;
// Open the popup.
p.IsOpen = true;
p.UpdateLayout();
border.Height = panel2.DesiredSize.Height + 5.0 * 2.0;
border.SetValue(Canvas.TopProperty, (height - border.Height) / 2.0);
border.SetValue(Canvas.LeftProperty, (width - border.Width) / 2.0);
p.UpdateLayout();
}
void closeButton_Click(object sender, RoutedEventArgs e)
{
// Close the popup.
p.IsOpen = false;
if (Dismissed != null)
{
Dismissed(Name, false, -1);
}
}
void radio1_Checked(object sender, int idx)
{
p.IsOpen = false;
if (Dismissed != null)
{
Dismissed(Name, idx != oldValue, idx);
}
}
}
I would suggest creating a Usercontrol that would do what you need. Set the LayoutRoot grid's background to PhoneSemitransparentBrush or changing the opacity will change the child element's opacity as well. Then your child elements can have any opacity you'd like. You can add this control as a child to the popup. Additionally, you can add doubleanimation to the popup with the opened and closed event triggers. Change the design height of the UserControl to 480x760 to simulate full page.
To answer your question. Using resources like PhoneSemitransparentBrush and TransparentBrush for the Canvas background is one of your options. Opacity will change the opacity of the whole UIElement including its children.