As per the title, I DO not want that to happen.
I have 2 separate labels and I want to make them flash provided an if statement is met. But whenever either label animates, the second label automatically follows to animate. I tried to test it by just changing the foreground color of the label and it works. The problem seems to occur only when I use the animation. Can anyone please help to spot my problem please. Tnks.
void AlertAnimation(Label label)
{
label.Foreground.BeginAnimation(SolidColorBrush.ColorProperty,
new ColorAnimation
{
To = Colors.Red,
Duration = TimeSpan.FromSeconds(0.1),
AutoReverse = true,
RepeatBehavior = new RepeatBehavior(3)
});
}
void calc()
{
if (maxValue > slider1.Value)
{
AlertAnimation(label10);
//label10.Foreground = Brushes.Red; //it works when I use this line.
}
else if (minValue < slider2.Value)
{
AlertAnimation(label11);
//label11.Foreground = Brushes.Red;
}
}
Related
I want to show the second stack layout when the first stack layout is clicked with an animation. It works well after the first attempt.
My question is the animation doesn't work for the first attempt.
code -
private TapGestureRecognizer tg;
public MainPage()
{
InitializeComponent();
answerStack.IsVisible = false;
tg = new TapGestureRecognizer();
tg.Tapped += Tg_Tapped;
questionStack.GestureRecognizers.Add(tg);
}
public Animation animate;
void Tg_Tapped(object sender, EventArgs e)
{
var answerHeight = answerStack.Height;
answerStack.IsVisible = !answerStack.IsVisible;
questionStack.GestureRecognizers.Remove(tg);
animate = new Animation(d => answerStack.HeightRequest = d, 0, answerHeight);
animate.Commit(answerStack, "a", 5, 450, Easing.CubicIn, (data, x) => {
Device.BeginInvokeOnMainThread(() => {
answerStack.HeightRequest = answerHeight;
questionStack.GestureRecognizers.Add(tg);
});
}, null);
}
GitHub Link - https://github.com/manieshavirt/XamarinAccordion
The reason for the issue is,"answerHeight" is set to -1 during the first animation. In subsequent animations,"answerHeight" is derived from the height of the answer-content, hence there is a smooth animation.If I manually set a value for "answerHeight" during the first animation, the animation transition appears smoothly. However, I do not want to set a value manually, instead, I need to derive the value from height of the answer-content during the first animation.
How can I achieve this?
I am attempting to make a stop light with the state pattern, so on my main window I have created three ellipses for each light color state. Within the main window I also have a button that will make a request to the light context.
private void startButton_Click(object sender, RoutedEventArgs e)
{
LightContext lc = new LightContext(new RedLight(),this);
lc.Request();
System.Threading.Thread.Sleep(3000);
lc.Request();
System.Threading.Thread.Sleep(3000);
lc.Request();
}
The way I have this set up is that after the context is created it makes the first request, which should set the light to the color red and gray out the two other lights, the system will then sleep for three seconds, make another request turning green, followed by yellow, then red again. The problem I am running into is that the colors do not change until the last request is made.. Which turns the light back to red so it looks like the light has never changed. If I comment out say the last request the light turns yellow once the two requests are done? How can I make the light change on each request then sleep so you can easily see the light change color.
public LightState LightState
{
get { return lightState; }
set
{
SolidColorBrush mySolidColorBrush = new SolidColorBrush();
lightState = value;
if (lightState.GetType().Name == nameof(RedLight))
{
mainWindow.RedLight.Fill = new SolidColorBrush(System.Windows.Media.Colors.Red);
mainWindow.YellowLight.Fill = new SolidColorBrush(System.Windows.Media.Colors.LightGray);
mainWindow.GreenLight.Fill = new SolidColorBrush(System.Windows.Media.Colors.LightGray);
}
else if (lightState.GetType().Name == nameof(YellowLight))
{
mainWindow.YellowLight.Fill = new SolidColorBrush(System.Windows.Media.Colors.Yellow);
mainWindow.GreenLight.Fill = new SolidColorBrush(System.Windows.Media.Colors.LightGray);
mainWindow.RedLight.Fill = new SolidColorBrush(System.Windows.Media.Colors.LightGray);
}
else if (lightState.GetType().Name == nameof(GreenLight))
{
mainWindow.GreenLight.Fill = new SolidColorBrush(System.Windows.Media.Colors.Green);
mainWindow.RedLight.Fill = new SolidColorBrush(System.Windows.Media.Colors.LightGray);
mainWindow.YellowLight.Fill = new SolidColorBrush(System.Windows.Media.Colors.LightGray);
}
}
I have a problem I've been looking into for a few days now, I just can't think of a logical way of doing what I want.
I have an app which has a task list. It starts of with 3 controls: a textbox, datetimepicker and a PictureBox which changes image on click. The user can then press an image which will add another row of controls below (It gets the properties of the dynamic controls from the controls already created):
https://www.dropbox.com/s/o2pub6orww24w25/tasklist.png (This is a screenshot to make it clearer)
Now what I want to do is save the values from each of the rows (A row being defined as: Textbox, Date, Status) into an SQLite DB.
For the first row it is easy, because that has a unique design name (and is a 'static' control).
However, the problem hits when I attempt to save values from the dynamic controls:
Problem a) I cannot reference the dynamic control because 'It does not Exist in the current Context'. -The function for creating the controls has a public access modifier so I thought that should do the trick? -It didn't. I've also tried:Panel1.pb.blah but it still didn't recognize the control?
Problem b) How can I tell my program that each row is a new set of data? In other words, how can I run a new insert command for each row? -I thought of doing this as a for-each-textbox loop, however would that not just pick up the first dynamic date everytime?
I've also thought of using the tag property and setting it to the counter variable, to group the controls in the row. (The counter being an integer which increments every time a new row is added.) However I cannot do that because the picture box uses the tag property as part of its function to change image on click (Changes multiple times).
Code:
Adding the Controls:
public void pictureBox1_Click(object sender, EventArgs e)
{
//TextBox Control
int tbh = tasktb.Location.Y + (counter*25);
int tbsh = tasktb.Size.Height;
int tbsw = tasktb.Size.Width;
TextBox tb = new TextBox();
tb.Location = new Point(9, tbh);
tb.Size = new System.Drawing.Size(tbsw, tbsh);
tb.Tag = counter.ToString();
//Date Time Control
int dth = duedatedb.Location.Y + (counter * 25);
int dtsh = duedatedb.Size.Height;
int dtsw = duedatedb.Size.Width;
DateTimePicker dtp = new DateTimePicker();
dtp.Location = new Point(300, dth);
dtp.Size = new Size(dtsw, dtsh);
dtp.Format = System.Windows.Forms.DateTimePickerFormat.Short;
//Picture Box Control
int stsh = status.Location.Y + (counter * 25);
int stssh = status.Size.Height;
int stssw = status.Size.Width;
PictureBox pb = new PictureBox();
pb.Location = new Point(429, stsh);
pb.Size = new Size(stssw, stssh);
pb.Image = Red;
pb.Click += new System.EventHandler(pb_Click);
panel1.Controls.Add(tb);
panel1.Controls.Add(dtp);
panel1.Controls.Add(pb);
++counter;
}
Trying to Reference the control: (For purposes of changing the image on click) [Found the Control.Find function from researching this in the MSDN Website]
public void pb_Click(object sender, EventArgs e)
{
PictureBox pb = (panel1.Controls.Find("pb",false));
if (pb.Image == Red) { pb.Image = Orange; status.Tag = "Orange"; }
else if (pb.Image == Orange) { pb.Image = green; status.Tag = "Green"; }
else if (pb.Image == green) { pb.Image = Red; status.Tag = "Red"; }
}
The essential problem here is Problem a, if you guys could see where I have gone wrong with that, I'd be able to go away and attempt to write some code to get around problem b.
(I have included Problem b in this for your suggestions on the best way to do this. -At the moment I have no clue!)
Thank you for any help received! It really is appreciated!
ControlCollection.Find looks for a control with the specified name, and you haven't set any. The variable names in your code aren't related. So, either:
pb.Name = "pb";
But that would mean you'd eventually have several items with the same name. So, seeing how you want to change the picture of the clicked PictureBox, just do this:
public void pb_Click(object sender, EventArgs e)
{
PictureBox pb = (PictureBox)sender;
if (pb.Image == Red) { pb.Image = Orange; status.Tag = "Orange"; }
else if (pb.Image == Orange) { pb.Image = green; status.Tag = "Green"; }
else if (pb.Image == green) { pb.Image = Red; status.Tag = "Red"; }
}
The sender argument always contains a reference to whichever control raised the event, in this case whichever picturebox was clicked!
Edit: As for your other question, I assume you'll need to do stuff to the controls later on, so I suggest you store a reference to all of them (or at least the ones you need), something like this:
// helper class
private class Entry
{
public TextBox TextBox { get; private set; }
public DateTimePicker DateTimePicker { get; private set; }
public PictureBox PictureBox { get; private set; }
public Entry( TextBox tb, DateTimePicker dtp, PictureBox pb )
{
this.TextBox = tb;
this.DateTimePicker = dtp;
this.PictureBox = pb;
}
}
// member field
private List<Entry> m_Entries = new List<Entry>();
// at the end of pictureBox1_Click
public void pictureBox1_Click(object sender, EventArgs e)
{
....
m_Entries.Add( new Entry( tb, dtp, pb ) );
}
Then you can use the items in that list to interact with your rows. You might also want to add an index, or a reference to whatever the original data structure is. Also, you might want to think about if you really should be creating the controls yourself like that or actually use some kind of table/grid control to host them!
Or perhaps just wrap up all those controls in a single UserControl, with logic included and all!
I'm a little new to this sort of coding, but i am trying to access dynamically created TextBlock properties (like, TextBlock.Tag, Name, etc) within a StackPanel every tick of a timer. What i intend to do with each TextBlock is to see what its tag property is, and if it matches a conditoinal, for the timer to alter the TextBlock property in some way.
So it's a matter of finding a way to code every timer Tick: "For every TextBlock.Tag in StackPanel, if TextBlock.Tag == this, do this to the TextBlock."
Here is some code to help visualize what I am doing:
Xaml code:
<StackPanel Name="StackP" Margin="6,0,6,0"/>
C# code:
{
for (var i = 0; i < MaxCountOfResults; ++i)
{
TextBlock SingleResult= new TextBlock { Text = Resultname.ToString(), FontSize = 20, Margin = new Thickness(30, -39, 0, 0) };
//a condition to alter certain TextBlock properties.
if (i == .... (irrelevant to this example))
{
SingleResult.Foreground = new SolidColorBrush(Colors.Yellow);
SingleResult.Tag = "00001";
}
//Add this dynamic TextBlock to the StackPanel StackP
StackP.Children.Add(SingleResult);
}
//the timer that starts when this entire function of adding the TextBlocks to the StackPanel StackP tree is done.
Atimer = new Timer(new TimerCallback(Atimer_tick), 0, 0, 100);
}
public void Atimer_tick(object state)
{
The area where I have no idea how to reference the Children of stackpanel StackP with every timer tick. I need help :(
}
Thank you guys. I am still learning this and the help is needed.
you should be able to use timer, but I'd recommend using BackgroundWorker to perform a loop instead of timer events, which could collide. Even better - use SilverLight-style animations with triggers.
On the non-UI thread you'd want to use Dispatcher call to invoke your async code back on the UI thread, something like:
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
try
{
foreach (TextBlock txb in StackP.Children){
txb.Text = "xyz";
}
}
catch (Exception ex)
{
Debug.WriteLine("error: "+ex);
}
});
For scrolling the datagrid, I use following code:
dataGridView1.FirstDisplayedScrollingRowIndex = currentRowIndexInGridView;
dataGridView1.Update();
That works fine for rows not at the bottom of the grid.
If I use it for bottom rows, the setter doesnt set it to the value I wanted, when I inspect it during debugging.
E.g. I am setting FirstDisplayedScrollingRowIndex= 103, but after the assignment FirstDisplayedScrollingRowIndex has the value 90 and hence the desired row is not visible.
From a certain point it stops scrolling and I cant see the last 5 rows.
If I am adding new rows and setting them to be displayed, it scrolls by one, but I dont see the last 5 rows again.
I think it has something to do with the fact, the some of my rows have different height and some internal estiment of DisplayedRowCount fails ???
Is there a way of detecting this situation and then forcing scrolling to the bottom of the datagrid?
EDIT:
The important part of the FirstDisplayedScrollingRowIndex setter looks like this in the Reflector:
if (value > this.displayedBandsInfo.FirstDisplayedScrollingRow)
{
int rows = this.Rows.GetRowCount(DataGridViewElementStates.Visible, this.displayedBandsInfo.FirstDisplayedScrollingRow, value);
this.ScrollRowsByCount(rows, (rows > 1) ? ScrollEventType.LargeIncrement : ScrollEventType.SmallIncrement);
}
else
{
this.ScrollRowIntoView(-1, value, true, false);
}
There seems to be an error in computing the rows variable.
Call following method whenever a new row is added
private void Autoscroll()
{
if (dgv.FirstDisplayedScrollingRowIndex + dgv.DisplayedRowCount(false) < dgv.Rows.Count)
{
dgv.FirstDisplayedScrollingRowIndex += dgv.DisplayedRowCount(false);
}
else
{
dgv.FirstDisplayedScrollingRowIndex = dgv.Rows.Count - 1;
}
}
I had to force all the rows to have the same width, otherwise the
FirstDisplayedScrollingRowIndex
setter is buggy.
I have similar issue but I found how to solved.
The problem seams to be that DataGridView required windows form refresh and only after that can be set FirstDisplayedScrollingRowIndex to the new index.
What I did?
Timer refreshTimer = new Timer();
public void RefreshLog()
{
dataGridViewVesselLog.DataSource = Log.Items;
dataGridViewVesselLog.Update();
dataGridViewVesselLog.Refresh();
refreshTimer.Interval = 100;
refreshTimer.Tick += (s, e) =>
{
if (dataGridViewVesselLog.Rows.Count > 0)
{
foreach (DataGridViewRow r in dataGridViewVesselLog.SelectedRows)
r.Selected = false;
dataGridViewVesselLog.Rows[dataGridViewVesselLog.Rows.Count - 1].Selected = true;
dataGridViewVesselLog.FirstDisplayedScrollingRowIndex = (int)(dataGridViewVesselLog.Rows.Count - 1);
}
refreshTimer.Stop();
}
refreshTimer.Start();
}