I have a UniformGrid which containts a bunch of buttons and when the UniformGrid first displays it cycles through animating each button to appear. This all works fine but when the user pushes a certain button all the buttons are removed from the grid and some new ones are created in and again are animated.
Here is how I create the buttons in code
int ModelsAnimateIndex = 0; // Index of button to animate
private void GetModels()
{
DirectoryInfo di = new DirectoryInfo(Globals.ModelsPath);
FileInfo[] fis = di.GetFiles();
// ugModels is the UniformGrid
switch (fis.Length)
{
case 1:
ugModels.Rows = 1;
ugModels.Columns = 1;
break;
case 2:
ugModels.Rows = 1;
ugModels.Columns = 2;
break;
case 3:
case 4:
ugModels.Rows = 2;
ugModels.Columns = 2;
break;
case 5:
case 6:
ugModels.Rows = 2;
ugModels.Columns = 3;
break;
case 7:
case 8:
case 9:
ugModels.Rows = 3;
ugModels.Columns = 3;
break;
default:
break;
}
foreach (FileInfo s in fis)
{
ugModels.Children.Add(new Button()
{
Background = ThemeColour, // SolidBrush
Foreground = new SolidColorBrush(Colors.White),
Name = "btn" + s.Name.Split('.')[0].Replace(" ",""),
Style = MainButtonStyle, // Button Style
Content = s.Name.Split('.')[0]
});
}
}
and now the button click event which starts animating the newly created buttons
private void btnModelSelect_Click(object sender, System.Windows.RoutedEventArgs e)
{
// TODO: Add event handler implementation here.
sbShowMenuButton.Completed += new EventHandler(sbShowModels_Completed);
Storyboard.SetTargetName(sbShowMenuButton.Children[0], ((Button)ugModels.Children[ModelsAnimateIndex]).Name);
Storyboard.SetTargetName(sbShowMenuButton.Children[1], ((Button)ugModels.Children[ModelsAnimateIndex]).Name);
Storyboard.SetTargetName(sbShowMenuButton.Children[2], ((Button)ugModels.Children[ModelsAnimateIndex]).Name);
sbShowMenuButton.Begin((Button)ugModels.Children[ModelsAnimateIndex]); // Error is here
}
When the first button tries to animate I get the following error
'btnTestModel' name cannot be found in the name scope of 'System.Windows.Controls.Button'.
I have solved my problem. I needed to create the RenderTransform on the buttons created like so.
foreach (FileInfo s in fis)
{
ugModels.Children.Add(new Button()
{
Background = ThemeColour,
// This Fixed the problem //
RenderTransform = new TransformGroup()
{
Children = new TransformCollection()
{
new ScaleTransform(),
new SkewTransform(),
new RotateTransform(),
new TranslateTransform()
}
},
////////////////////////////////////////////////
BorderBrush = null,
Foreground = new SolidColorBrush(Colors.White),
Name = "btn" + s.Name.Split('.')[0].Replace(" ", ""),
Margin = new Thickness(12, 12, 12, 12),
FontSize = 48,
Style = MainButtonStyle,
Content = s.Name.Split('.')[0]
});
}
thanks to Matt's sugestion, I also modified setting the storyboard
private void btnMenu_Click(object sender, System.Windows.RoutedEventArgs e)
{
sbShowMenuButton.Completed += new EventHandler(sbShowModels_Completed);
Storyboard.SetTarget(sbShowMenuButton, ((Button)ugModels.Children[ModelsAnimateIndex]));
sbShowMenuButton.Begin();
}
Related
Is there any way of setting the Z-order of controls on a panel to always be on top when a new control is added? I am creating a card game and I have a Panel with the pictures of the cards in (a new picturebox for each card). When a new picture is added it automatically goes to the back of the panel. Is there any way so it will be always on top? I've tried 'SetChildIndex' but the name of each picturebox will be the same as I'm re-using code. Any help is appreciated. Thanks
private void DealPlayerCard(int cardNum)
{
string Card = Classes.Deck.GetCurrentCard();
PictureBox pb = new PictureBox() { Width = 172, Height = 240, SizeMode = PictureBoxSizeMode.StretchImage };
pb.ImageLocation = #"Cards\" + Card + ".png";
int order = 0;
switch (cardNum)
{
case 1:
pb.Location = new Point(0, 0);
order = 5;
break;
case 2:
pb.Location = new Point(60, 0);
order = 4;
break;
case 3:
pb.Location = new Point(120, 0);
order = 3;
break;
case 4:
pb.Location = new Point(180, 0);
order = 2;
break;
case 5:
pb.Location = new Point(240, 0);
order = 1;
break;
}
AddPlayerCard(pb, order);
}
public void AddPlayerCard(PictureBox pb, int order)
{
pnlPlayer.Controls.Add(pb);
pnlPlayer.Controls.SetChildIndex(pb, order);
}
EDIT
Using Sinatr's idea, I have now used the .Tag control property to give the z-order number to each of the controls and then whenever I add a control - simply loop through each control and set the z-order = .Tag property
private void DealPlayerCard(int cardNum)
{
string Card = Classes.Deck.GetCurrentCardPicture();
PictureBox pb = new PictureBox() { Width = 172, Height = 240, SizeMode = PictureBoxSizeMode.StretchImage };
pb.ImageLocation = #"Cards\" + Card + ".png";
switch (cardNum)
{
case 1:
pb.Location = new Point(0, 0);
pb.Tag = 5;
break;
case 2:
pb.Location = new Point(60, 0);
pb.Tag = 4;
break;
case 3:
pb.Location = new Point(120, 0);
pb.Tag = 3;
break;
case 4:
pb.Location = new Point(180, 0);
pb.Tag = 2;
break;
case 5:
pb.Location = new Point(240, 0);
pb.Tag = 1;
break;
}
AddPlayerCard(pb);
AddToHand("Player");
}
public void AddPlayerCard(PictureBox pb)
{
pnlPlayer.Controls.Add(pb);
foreach (Control Control in pnlPlayer.Controls)
{
pnlPlayer.Controls.SetChildIndex(Control, Int32.Parse(Control.Tag.ToString()));
}
}
You can use the BringToFront() method, available to every Winform control:
controlName.BringToFront();
This brings the control controlName to the top of the z-order, forcing it to have a z-order of 0.
You can SetChildIndex(System.Windows.Forms.Control child, int newIndex) to set the z-order.
A control with newIndex set to 0, is at the top of the z-order. Controls with higher newIndex will be positioned closer to the bottom.
I am building a poker game where I need to show multiple poker hands at the same time. I can either show 1, 3, 5, or 10.
I have 1 main hand that will display all the time and I activate different views based on the amount of hands the player wants to play.
I have 2 main panels (main_hand_panel, and extra_hands_panel)
I add all the Panels in a List and when it's time, I call ShowHand on it.
I add the first poker hand to main_hand_panel like this:
Point startPosition = new Point(0, 0);
ComponentResourceManager resources = new ComponentResourceManager(typeof(MainScreen));
var mainPokerHand = new PokerPanel(startPosition, main_hand_panel.Size, offset, cardSize);
mainPokerHand.Initialize(resources);
this.main_hand_panel.Controls.Add(mainPokerHand);
allHands.Add(mainPokerHand);
Then depending on which screen I'm showing I draw and add the additional hands like this (five hands example shown)
public void DrawFivePlay(ComponentResourceManager resources)
{
Point startPosition = new Point(0, 0);
var containerSize = extra_hands_panel.Size;
containerSize.Height = Convert.ToInt32(containerSize.Height / 2);
containerSize.Width = Convert.ToInt32(containerSize.Width / 2);
for (int i = 0; i < 2; i++)
{
startPosition.Y = containerSize.Height * i;
var pokerHand = new PokerPanel(startPosition, containerSize, scale(offset, .30), scale(cardSize, .8));
pokerHand.Initialize(resources);
this.extra_hands_panel.Controls.Add(pokerHand);
allHands.Add(pokerHand);
}
startPosition.X = containerSize.Width;
startPosition.Y = 0;
for (int i = 0; i < 2; i++)
{
startPosition.Y = containerSize.Height * i;
var pokerHand = new PokerPanel(startPosition, containerSize, scale(offset, .30), scale(cardSize, .8));
pokerHand.Initialize(resources);
this.extra_hands_panel.Controls.Add(pokerHand);
allHands.Add(pokerHand);
}
}
When I'm ready to show the hands, I call reveal_click which goes through all the hands in List and displays them.
private void reveal_Click(object sender, EventArgs e)
{
foreach (var hand in allHands)
{
hand.ShowHand();
}
Application.DoEvents();
}
The interesting part is that it doesn't display the main hand, it will display all the others, but the only time it displays the first hand is when the program just started and we are playing only 1 hand. If I show any of the other play option, the first hand will not display anymore.
Here is the PokerPanel code:
namespace TEX_DrawPoker
{
public class PokerPanel : Panel
{
private PictureBox pictureBox1_5;
private PictureBox pictureBox1_1;
private PictureBox pictureBox1_2;
private PictureBox pictureBox1_3;
private PictureBox pictureBox1_4;
Timer drawTimer = new Timer();
int timerTick = 0;
string[] pokerHand;
Size panelSize = new Size(5*229, 275);
Size cardSize = new Size(146, 202);
Point startPosition = new Point(0, 3);
Point firstCardPosition = new Point(0, 0);
Point offset = new Point(160, 0);
public PokerPanel(Point _startPosition,Size _panelSize, Point _offset, Size _cardSize)
{
drawTimer.Tick += new EventHandler(startDisplay);
drawTimer.Interval = 100;
drawTimer.Enabled = false;
panelSize = _panelSize;
cardSize = _cardSize;
offset = _offset;
startPosition = _startPosition;
}
public void startDisplay(object sender, EventArgs e)
{
switch (timerTick)
{
case 0:
this.pictureBox1_1.Image = (Image)(new Bitmap(Image.FromFile(".\\img\\cards\\" + pokerHand[timerTick] + ".png"), cardSize));
break;
case 1:
this.pictureBox1_2.Image = (Image)(new Bitmap(Image.FromFile(".\\img\\cards\\" + pokerHand[timerTick] + ".png"), cardSize));
break;
case 2:
this.pictureBox1_3.Image = (Image)(new Bitmap(Image.FromFile(".\\img\\cards\\" + pokerHand[timerTick] + ".png"), cardSize));
break;
case 3:
this.pictureBox1_4.Image = (Image)(new Bitmap(Image.FromFile(".\\img\\cards\\" + pokerHand[timerTick] + ".png"), cardSize));
break;
case 4:
this.pictureBox1_5.Image = (Image)(new Bitmap(Image.FromFile(".\\img\\cards\\" + pokerHand[timerTick] + ".png"), cardSize));
break;
}
if (timerTick >= 4)
{
drawTimer.Stop();
timerTick = 0;
}
else
{
timerTick++;
}
}
public void ShowHand()
{
pokerHand = Deck.shuffle();
drawTimer.Start();
}
public void Reset()
{
Image back = Image.FromFile(".\\img\\cards\\back.png");
this.pictureBox1_1.Image = (Image)(new Bitmap(back, cardSize));
this.pictureBox1_2.Image = (Image)(new Bitmap(back, cardSize));
this.pictureBox1_3.Image = (Image)(new Bitmap(back, cardSize));
this.pictureBox1_4.Image = (Image)(new Bitmap(back, cardSize));
this.pictureBox1_5.Image = (Image)(new Bitmap(back, cardSize));
}
public void Initialize(ComponentResourceManager resources)
{
Image back = Image.FromFile(".\\img\\cards\\back.png");
this.pictureBox1_1 = new System.Windows.Forms.PictureBox();
this.pictureBox1_2 = new System.Windows.Forms.PictureBox();
this.pictureBox1_3 = new System.Windows.Forms.PictureBox();
this.pictureBox1_4 = new System.Windows.Forms.PictureBox();
this.pictureBox1_5 = new System.Windows.Forms.PictureBox();
((System.ComponentModel.ISupportInitialize)(this.pictureBox1_1)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.pictureBox1_2)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.pictureBox1_3)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.pictureBox1_4)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.pictureBox1_5)).BeginInit();
this.SuspendLayout();
//
// hand_1
//
this.Controls.Add(this.pictureBox1_5);
this.Controls.Add(this.pictureBox1_4);
this.Controls.Add(this.pictureBox1_3);
this.Controls.Add(this.pictureBox1_2);
this.Controls.Add(this.pictureBox1_1);
this.Location = startPosition;
this.Name = "hand_1";
this.Size = panelSize;
this.TabIndex = 0;
//
// pictureBox1_1
//
this.pictureBox1_1.Image = (Image)(new Bitmap(back, cardSize));
this.pictureBox1_1.Location = firstCardPosition;
this.pictureBox1_1.Name = "pictureBox1_1";
this.pictureBox1_1.Size = cardSize;
this.pictureBox1_1.TabIndex = 4;
this.pictureBox1_1.TabStop = false;
//
// pictureBox1_2
//
var positionCard_2 = firstCardPosition;
positionCard_2.Offset(offset);
this.pictureBox1_2.Image = (Image)(new Bitmap(back, cardSize));
this.pictureBox1_2.Location = positionCard_2;
this.pictureBox1_2.Name = "pictureBox1_2";
this.pictureBox1_2.Size = cardSize;
this.pictureBox1_2.TabIndex = 3;
this.pictureBox1_2.TabStop = false;
//
// pictureBox1_3
//
var positionCard_3 = positionCard_2;
positionCard_3.Offset(offset);
this.pictureBox1_3.Image = (Image)(new Bitmap(back, cardSize));
this.pictureBox1_3.Location = positionCard_3;
this.pictureBox1_3.Name = "pictureBox1_3";
this.pictureBox1_3.Size = cardSize;
this.pictureBox1_3.TabIndex = 2;
this.pictureBox1_3.TabStop = false;
//
// pictureBox1_4
//
var positionCard_4 = positionCard_3;
positionCard_4.Offset(offset);
this.pictureBox1_4.Image = (Image)(new Bitmap(back, cardSize));
this.pictureBox1_4.Location = positionCard_4;
this.pictureBox1_4.Name = "pictureBox1_4";
this.pictureBox1_4.Size = cardSize;
this.pictureBox1_4.TabIndex = 1;
this.pictureBox1_4.TabStop = false;
//
// pictureBox1_5
//
var positionCard_5 = positionCard_4;
positionCard_5.Offset(offset);
this.pictureBox1_5.Image = (Image)(new Bitmap(back, cardSize));
this.pictureBox1_5.Location = positionCard_5;
this.pictureBox1_5.Name = "pictureBox1_5";
this.pictureBox1_5.Size = cardSize;
this.pictureBox1_5.TabIndex = 0;
this.pictureBox1_5.TabStop = false;
((System.ComponentModel.ISupportInitialize)(this.pictureBox1_5)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.pictureBox1_4)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.pictureBox1_3)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.pictureBox1_2)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.pictureBox1_1)).EndInit();
}
}
}
I also use a timer to display the cards so that they stagger.
Any help would be appreciated.
Thanks,
Found my problem,
I was not clearing the controls between hand changes, so I was trying to update a panel that was in the background. Controls.Clear() before moving to the next hand fixed that for me. Sorry for the long post for nothing. :(
Have you considered refreshing the entire form?
Form1.Refresh();
or only refresh the panel
PokerPanel.Refresh();
I am building a window from code.
I add a header TextBlock and then some various elements for a listBox in which each element is made out of
Grid ---> children[0] a TextBlock to explain what is the element
---> children1 a TextBox or combobox to input data.
At the end a button.
After having generated put the focus on the first element (generally the first TextBox) so that the user can immediately input data. Up to that everything works.
--ADD--
I forgot to mention that every element = Grid = Textblock + TextBox or combobox, is an element of the parent listBox. So I would like to move from every textbox or combobox independently from the listbox element they are in.
After that I want the user to be able to move to next element (textbox or combobox) through TAB. So when generating the previous windows I use a counter and set
tb.TabIndex = tabIndex++;
or
ComboBox.TabIndex = tabIndex++;
Now the problem is that after having input data in the first TextBox when I press TAB the caret gets lost and so the focus...
---ADD2---
Here is the code:
private void PreparareTraceFieldGrid(ListBox lbTracefields, ObservableCollection<Tuple<string, object, object>> obc, bool IsReadOnly)
{
bool IsFocusSet = false;
/*---TITOLO---*/
OutlinedTextBlock otbTitle = CreateOtbForTraceFieldInputWindow(Languages.Word(eWords.InsertTracefields));
lbTracefields.Items.Add(otbTitle);
/*----CICLO----*/
int tabIndex = 0;
foreach (var item in obc)
{
Grid gridInternal = new Grid();
gridInternal.Background = Brushes.Transparent;
ColumnDefinition cd1 = new ColumnDefinition();
cd1.Width = new GridLength(300, GridUnitType.Pixel);
ColumnDefinition cd2 = new ColumnDefinition();
cd2.Width = new GridLength(1.0, GridUnitType.Star);
gridInternal.ColumnDefinitions.Add(cd1);
gridInternal.ColumnDefinitions.Add(cd2);
OutlinedTextBlock otb = CreateOtbForTraceFieldInputWindow(item.Item1);
otb.FontSize = easyRunData.OptionsGraphical.FontSize;
otb.Stroke = new SolidColorBrush(easyRunData.OptionsGraphical.StrokeColour);
otb.StrokeThickness = easyRunData.OptionsGraphical.StrokeSize;
Grid.SetColumn(otb, 0);
gridInternal.Children.Add(otb);
string strDataType = item.Item2.ToString();
eTraceFieldDataTypes eDataType = (eTraceFieldDataTypes)Enum.Parse(typeof(eTraceFieldDataTypes), strDataType);
switch (eDataType)
{
case eTraceFieldDataTypes.STRING:
case eTraceFieldDataTypes.FLOAT:
case eTraceFieldDataTypes.INTEGER:
case eTraceFieldDataTypes.STRING_READONLY:
TextBox tb = new TextBox();
tb.CaretBrush = Brushes.White;
tb.FontSize = easyRunData.OptionsGraphical.FontSize;
tb.MinWidth = 200;
tb.Height = easyRunData.OptionsGraphical.FontSize + 15;
tb.VerticalAlignment = VerticalAlignment.Center;
tb.Background = Brushes.Transparent;
tb.Margin = new Thickness(10);
tb.TabIndex = tabIndex++;
tb.KeyDown += (senderEvent, args) => { AnalyzeTraceFields_IF_EMPTY(easyRunData.Tracefields.TraceFieldsUser, (Grid)lbTracefields.Parent); };
if (eDataType == eTraceFieldDataTypes.STRING_READONLY && !IsReadOnly)
tb.BorderBrush = Brushes.Yellow;
else
tb.BorderBrush = Brushes.Gainsboro;
Grid.SetColumn(tb, 1);
gridInternal.Children.Add(tb);
lbTracefields.Items.Add(gridInternal);
if (!IsFocusSet)
{
tb.Focus();
IsFocusSet = true;
}
break;
case eTraceFieldDataTypes.BOOL:
case eTraceFieldDataTypes.BOOL_READONLY:
Border brd = new Border();
brd.Margin = new Thickness(10);
brd.MinWidth = 200;
brd.Height = easyRunData.OptionsGraphical.FontSize + 15;
if (eDataType == eTraceFieldDataTypes.BOOL_READONLY && !IsReadOnly)
brd.BorderBrush = Brushes.Yellow;
else
brd.BorderBrush = Brushes.Gainsboro;
brd.BorderThickness = new Thickness(3);
ComboBox cmb = new ComboBox();
cmb.VerticalAlignment = VerticalAlignment.Center;
cmb.Background = Brushes.Transparent;
cmb.Items.Add(Languages.Word(eWords.True));
cmb.Items.Add(Languages.Word(eWords.False));
cmb.BorderBrush = Brushes.Gainsboro;
cmb.BorderThickness = new Thickness(3);
cmb.Margin = new Thickness(0);
cmb.TabIndex = tabIndex++;
cmb.DropDownClosed += (senderEvent, args) => { AnalyzeTraceFields_IF_EMPTY(easyRunData.Tracefields.TraceFieldsUser, (Grid)lbTracefields.Parent); };
Grid.SetColumn(brd, 1);
brd.Child = cmb;
gridInternal.Children.Add(brd);
lbTracefields.Items.Add(gridInternal);
if (!IsFocusSet)
{
cmb.Focus();
IsFocusSet = true;
}
break;
default:
break;
}
}
I want to programmatically create a panel and add some pictureBoxes where i select the image through a for loop. I tried lots of ways but the form shows empty.
My code is :
private void draw_pipeline()
{
Panel pnl = new Panel();
pnl.Size = new System.Drawing.Size(1130, 145);
pnl.Location = new Point(380, 260);
pnl.BorderStyle = BorderStyle.FixedSingle;
for (int i =0; i<3; i++)
{
PictureBox pic = new PictureBox();
pic.SizeMode = PictureBoxSizeMode.Zoom;
switch (i)
{
case 0:
{
pic.Location = new Point(3, 15);
pic.Size = new Size(73, 121);
pic.Image = new Bitmap("if.png"); break;
}
case 1:
{
pic.Location = new Point(76, 15);
pic.Size = new Size(73, 121);
pic.Image = new Bitmap("line.png"); break;
}
}
pnl.Controls.Add(pic);
}
}
the result i want to create is illustrated in the picture below, that contains two picture boxes with two images, if.png which is the if-box image and the line.png which is the line image. I repeat the result of my code is that form shows empty!! Any help?
You'll need to add the Panel to the Form at some point, in the same way you're adding PictureBoxes to the Panel:
this.Controls.Add(pnl);
(The this is assuming that your draw_pipeline method belongs to the Form to which you're trying to add the Panel.)
I've got the following UIActionSheet.
How do I add it to my top navigation bar?
Preferably as the far right button.
var sheet = new UIActionSheet ("");
sheet.AddButton ("Discard Picture");
sheet.AddButton ("Pick New Picture");
sheet.AddButton ("Cancel");
sheet.CancelButtonIndex = 2;
// Dummy buttons to preserve the space for the UIImageView
for (int i = 0; i < 4; i++) {
sheet.AddButton("");
sheet.Subviews[i+4].Alpha = 0; // And of course it's better to hide them
}
var subView = new UIImageView();
subView.ContentMode = UIViewContentMode.ScaleAspectFill;
subView.Frame = new RectangleF(23,185,275,210);
// Late Steve Jobs loved rounded corners. Let's have some respect for him
subView.Layer.CornerRadius = 10;
subView.Layer.MasksToBounds = true;
subView.Layer.BorderColor = UIColor.Black.CGColor;
sheet.AddSubview(subView);
NavigationController.Add(sheet);
You can show an ActionSheet using the ShowFrom methods.
In particular, ShowFromToolbar shows the sheet from the top toolbar button.
Here's an example which shows the sheet in different ways depending on whether you are on tablet or phone:
void ActionMenu()
{
//_actionSheet = new UIActionSheet("");
UIActionSheet actionSheet = new UIActionSheet (
"Customer Actions",
null,
"Cancel",
"Delete Customer",
new string[] {"Change Customer"});
actionSheet.Style = UIActionSheetStyle.Default;
actionSheet.Clicked += delegate(object sender, UIButtonEventArgs args) {
switch (args.ButtonIndex)
{
case 0: DeleteCustomer(); break;
case 1: ChangeCustomer(); break;
}
};
if (UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Phone)
actionSheet.ShowFromToolbar(NavigationController.Toolbar);
else
actionSheet.ShowFrom(NavigationItem.RightBarButtonItem, true);
}
https://github.com/slodge/MvvmCross-Tutorials/blob/master/Sample%20-%20CustomerManagement/CustomerManagement/CustomerManagement.Touch/Views/CustomerView.cs#L67