winforms, help needed to create a dynamic tablelayoutpanel with buttons - visual-studio

I am trying to create a dynamic tablelayout which creates adds a skill and gives that skill 1 level and a increase decrease button. I am struggling with having the buttons access the level label. I thought about finding the location of the button that was clicked, but could figure out how to do that.
In advance, Thank you.
example:
1
this is what i have so far:
private void skilladded(object sender, EventArgs e)
{
int i = 1;
int[] position= { 0,0};
bool test = false;
//string select;
int k=0;
for (i=1;i<=skillstableLayoutPanel.RowCount;i++)
{
Control c= skillstableLayoutPanel.GetControlFromPosition(0,i);
if (c!=null&&addskillswin.selected==c.Text)
{
test = true;
k = i;
break;
}
else if(c==null)
{
k = i;
break;
}
}
if (test==false)
{
Label newskill = new Label();
Label newskilllvl = new Label();
TableLayoutPanel buttontable = new TableLayoutPanel();
Button up = new Button();
Button down = new Button();
buttontable.ColumnCount = 2;
buttontable.RowCount = 1;
buttontable.RowStyles.Add(new RowStyle(SizeType.Percent,100f));
buttontable.ColumnStyles.Add(new ColumnStyle(SizeType.Percent,50f));
buttontable.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50f));
buttontable.Margin = new Padding(0,0,0,0);
buttontable.Dock = DockStyle.Fill;
buttontable.Controls.Add(up, 0, 0);
buttontable.Controls.Add(down, 1, 0);
up.BackgroundImage = Properties.Resources.up;[enter image description here][2]
down.BackgroundImage = Properties.Resources.down;
up.BackgroundImageLayout=ImageLayout.Stretch;
down.BackgroundImageLayout = ImageLayout.Stretch;
newskill.Text = addskillswin.selected;
newskilllvl.Text = "1";
up.Margin = new Padding(0, 0, 0, 0);
down.Margin = new Padding(0, 0, 0, 0);
skillstableLayoutPanel.Controls.Add(newskill,0,k);
skillstableLayoutPanel.Controls.Add(newskilllvl, 1, k);
skillstableLayoutPanel.Controls.Add(buttontable, 2, k);
skillavaillabel.Text = (Convert.ToInt32(skillavaillabel.Text) - 1).ToString();
skillpointlvl = Convert.ToInt32(newskilllvl.Text);
up.MouseClick += new MouseEventHandler(skillup);
down.MouseClick += new MouseEventHandler(skilldown);
}
if (test==true)
{
skillstableLayoutPanel.GetControlFromPosition(1, k).Text = (Convert.ToInt32(skillstableLayoutPanel.GetControlFromPosition(1, k).Text) + 1).ToString();
skillavaillabel.Text = (Convert.ToInt32(skillavaillabel.Text) -1).ToString();
}
}
private void skillup(object sender, EventArgs e)
{
skillpointlvl++;
}
private void skilldown(object sender, EventArgs e)
{
skillpointlvl--;
}

Instead of this:
up.MouseClick += new MouseEventHandler(skillup);
down.MouseClick += new MouseEventHandler(skilldown);
Try something like this:
up.MouseClick += ((o, me) =>
{
int currentLevel = Int32.Parse(newskilllvl.Text);
currentLevel++;
newskilllvl.Text = currentLevel.ToString();
});
down.MouseClick += ((o, me) =>
{
int currentLevel = Int32.Parse(newskilllvl.Text);
currentLevel--;
newskilllvl.Text = currentLevel.ToString();
});
Your skillup or skilldown event handler could potentially process each sender and see from which button the click originated, but you'd have to uniquely name each button and do a lot of string comparisons to see which button corresponds to which skill level label. The code above adds an anonymous handler to each button, which allows us to essentially tie the button being clicked to its corresponding skill label.
Personally though, I would not store all these values in labels like you have done. I would either store them in properties on the form, or better yet in a class of their own. I would also put all this logic somewhere else beside the form, like in a Presenter or Controller (or class library), and follow a design pattern such as MVC or MVP. This will make maintaining and changing the application easier in the long run.
Also, consider using camel case and Pascal case for your variable names. All lowercase variables are harder for experienced programmers to read.

Related

Adding a swipe to next gesture using Syncfusion.SfChart

Currently on my app when the user selects their 'symptom' they are directed to the detail page which shows their symptom chart with the populated feedback data from their selected symptom.
Is their a way i can add a swipe gesture to allow the user to swipe to the next symptom chart without having to go back to main symptoms page and selecting a symptom.
Currently this is how i populate my chart :
public async Task GetSymptomFeedback(string id)
{
SymptomFeedbackData.Clear();
symptomChart.Series.Clear();
BusyIndicator.IsRunning = true;
SymptomFeedbackData = await symptomsfeedbackmanager.getUserSymptomFeedback(id);
foreach (var FeedbackItem in SymptomFeedbackData)
{
FeedbackItem.Idusersymptomid = FeedbackItem.Id + ',' + FeedbackItem.Usersymptomid;
}
IEnumerable<SymptomFeedback> OrdreredFeedbackData = SymptomFeedbackData.OrderBy(X => X.DateTime);
LineSeries columnseries = new LineSeries
{
ItemsSource = OrdreredFeedbackData,
XBindingPath = "DateTime",
YBindingPath = "Intensity",
DataMarker = new ChartDataMarker
{
ShowLabel = true,
ShowMarker = true,
MarkerHeight = 5,
MarkerWidth = 5,
MarkerColor = Xamarin.Forms.Color.Purple
}
};
BusyIndicator.IsRunning = false;
symptomChart.PrimaryAxis.ShowTrackballInfo = true;
if (columnseries.ItemsSource != null)
{
symptomChart.Series.Add(columnseries);
}
symptomChart.ChartBehaviors.Add(new ChartTrackballBehavior());
//Sort Collection by datetime
SymptomsList.ItemsSource = OrdreredFeedbackData.Reverse();
}
Solution:
Through your code, we can see you query the data through the id of symptom. So, I guess you pass this id as parameter when you go to the detail page from main symptoms page.
Is their a way i can add a swipe gesture to allow the user to swipe to
the next symptom chart without having to go back to main symptoms page
and selecting a symptom.
In additional, you can pass a array of id of all symptoms to detail page. Let's name this array as symptomIdArray.
Then add a SwipeGestureRecognizer to your view.
var DownSwipeGesture = new SwipeGestureRecognizer { Direction = SwipeDirection.Down };
var UpSwipeGesture = new SwipeGestureRecognizer { Direction = SwipeDirection.Up };
DownSwipeGesture.Swiped += OnSwiped;
UpSwipeGesture.Swiped += OnSwiped;
this.Content.GestureRecognizers.Add(DownSwipeGesture);
this.Content.GestureRecognizers.Add(UpSwipeGesture);
In the OnSwiped, you can get last or next id through the symptomIdArray and currentID , and then you can choose to reload your current page or go to a new page to swipe to the next symptom chart, here is code:
public Array symptomIdArray; // ids of all symptom
public string currentID; // You selected id of current symptom
void OnSwiped(object sender, SwipedEventArgs e)
{
int index = Array.IndexOf(symptomIdArray, currentID);
switch (e.Direction)
{
case SwipeDirection.Up:
if (index ==0)
{
//first one
break;
}
string lastID = (string)symptomIdArray.GetValue(index-1);
//1.You can refresh current page with lastId
GetSymptomFeedback(lastID);
//2.You can go to a new page with lastID ID and symptomIdArray
Navigation.PushAsync(new NewPage(lastID, symptomIdArray));
break;
case SwipeDirection.Down:
// Handle the swipe
if (index == symptomIdArray.Length-1)
{
//Last one, no more
break;
}
string nextID = (string)symptomIdArray.GetValue(index+1);
//1.You can refresh current page with next currentID
GetSymptomFeedback(nextID);
//2.You can go to a new page with nextID ID and symptomIdArray
Navigation.PushAsync(new NewPage(nextID, symptomIdArray));
break;
}
}
Update:
Add SwipeGestureRecognizer:
SfChart chart = new SfChart();
chart.Title.Text = "Chart";
//Config chart....
...
chart.Series.Add(series);
this.Content = chart;
var DownSwipeGesture = new SwipeGestureRecognizer { Direction = SwipeDirection.Down };
var UpSwipeGesture = new SwipeGestureRecognizer { Direction = SwipeDirection.Up };
DownSwipeGesture.Swiped += OnSwiped;
UpSwipeGesture.Swiped += OnSwiped;
chart.GestureRecognizers.Add(DownSwipeGesture);
chart.GestureRecognizers.Add(UpSwipeGesture);
And onSwipe:
void OnSwiped(object sender, SwipedEventArgs e)
{
switch (e.Direction)
{
case SwipeDirection.Up:
Console.WriteLine("up");
break;
case SwipeDirection.Down:
Console.WriteLine("down");
break;
}
}
Let me know if you have any question.

What is the function of Message sender in xamarin.forms

What is the function of Message sender in xamarin.forms? In my app I have cart contain list view and a Grant Total label. Is it possible to update the label using message sender? I can get the total amount from my sqlite db I need to update it to the view.
This is my number picker index change event in view cell
numPicker.SelectedIndexChanged += (sender, args) =>
{
// var price = _cartQuery.GetSum();
sender = BindingContext;
// cm_items item = (cm_items)sender;
if(Int32.Parse(btn_NumBtn.Text)<=1)
{
lbl_Price.Text = ((numPicker.SelectedIndex + 1) * (Int32.Parse(lbl_Price.Text))).ToString();
btn_NumBtn.Text = (numPicker.SelectedIndex + 1).ToString();
}
else
{
int a = Int32.Parse(lbl_Price.Text);
int b = Int32.Parse(btn_NumBtn.Text);
int c = a / b;
lbl_Price.Text = ((numPicker.SelectedIndex + 1) * c).ToString();
btn_NumBtn.Text = (numPicker.SelectedIndex + 1).ToString();
}
_cartQuery.UpdatePicker((BindingContext as CartDB).Cart_Item_Id, numPicker.SelectedIndex + 1, Int32.Parse(lbl_Price.Text));
price = _cartQuery.GetSum();
// App.Instance.ViewModel.TotalAmount = price;
// _cartDB.total = App.Instance.ViewModel.TotalAmount;
Calculate_price();
numPicker.IsEnabled = false;
};
Calculate_price method
public double Calculate_price()
{
try
{
var price = 0;
price = _cartQuery.GetSum();
App.Instance.ViewModel.TotalAmount = price;
return price;
}
catch (Exception ex)
{
throw ex;
}
}
In my view i have a label named grant total, i need to update the total on e number picker change
Label lbl_amnt = new Label
{
// Text = viewModel.Price.ToString(),
// Text=CartCell.price.ToString(),
Text = price.ToString(),
FontSize = 18,
FontAttributes = FontAttributes.Bold,
TextColor = Color.FromRgb(102, 204, 102),
VerticalOptions = LayoutOptions.CenterAndExpand,
HorizontalOptions = LayoutOptions.EndAndExpand,
};
lbl_amnt.SetBinding(Label.TextProperty, "TotalAmount");
update to my post as per the comment from #Grish
In my view model i have this TotalAmount as a property
public double _TotalAmount;
public double TotalAmount
{
get { return _TotalAmount; }
set { _TotalAmount = value; OnPropertyChanged("TotalAmount");}
}
I think the better solution is i notify but the thing is view is not binding
Binding is definitely the answer in your case. I think the problem is that you bind string (label's text) to property of type double.
You should specify IValueConverter or stringFormat parameters in your call to SetBinding.
Check this link:
https://forums.xamarin.com/discussion/19146/binding-to-integers

replacing a submitlink with indicatingAjaxButton

I have a form with a submitbutton which will get results from a database and updates a listview based on these results. If there is no result, a feedback message is shown. This all works fine.
Now I want to replace the submitlink with an IndicatingAjaxButton, so the user can see something happening when getting the result takes a long time.
The basic idea is this:
IndicatingAjaxButton submitLink = new IndicatingAjaxButton("submit", form) {
private static final long serialVersionUID = -4306011625084297054L;
#Override
public void onSubmit(AjaxRequestTarget target, Form<?> form) {
Integer hourFrom = 0;
Integer hourTo = 0;
Integer minuteFrom = 0;
Integer minuteTo = 0;
hourFrom = Integer.parseInt(hour_from.getModelObject());
hourTo = Integer.parseInt(hour_to.getModelObject());
minuteFrom = Integer.parseInt(minute_from.getModelObject());
minuteTo = Integer.parseInt(minute_to.getModelObject());
Calendar from = Calendar.getInstance();
Calendar to = Calendar.getInstance();
Date dateFrom = date_from.getModelObject();
Date dateTo = date_to.getModelObject();
from.setTime(dateFrom);
to.setTime(dateTo);
from.set(Calendar.HOUR, hourFrom);
from.set(Calendar.MINUTE, minuteFrom);
to.set(Calendar.HOUR, hourTo);
to.set(Calendar.MINUTE, minuteTo);
if (topicQueueSelect.getModelObject() == null) {
error("Please select a message name.");
getSession().setAttribute("error", "");
}
if (to.before(from)) {
error("Date to must be after date from.");
getSession().setAttribute("error", "");
}
cal.setTimeInMillis(System.currentTimeMillis());
if (from.after(cal)) {
error("Date from must be in the past.");
getSession().setAttribute("error", "");
}
if (getSession().getAttribute("error") != null) {
getSession().removeAttribute("error");
return;
}
page.setModelObject(1);
List<Search> searchFields = (List<Search>) searchFieldsField
.getModelObject();
messageKeyDataList = messageController.search(
topicQueueSelect.getModelObject(), searchFields,
from.getTime(), to.getTime(),
maxResults.getModelObject(), page.getModelObject(),
sortorder);
if (messageKeyDataList.size() == 0) {
info("Search criteria didn't produce any results.");
result.setList(messageKeyDataList);
resultContainer.setVisible(false);
return;
}
resultContainer.setVisible(true);
resultSize = messageController.getResultSize();
int pages = (int) Math.ceil((float) resultSize
/ maxResults.getModelObject());
ArrayList<Integer> pageNumbers = new ArrayList<Integer>();
for (int n = 1; n <= pages; n++) {
pageNumbers.add(n);
}
page.setChoices(pageNumbers);
pageunder.setChoices(pageNumbers);
showing.setDefaultModelObject("Showing 1 to "
+ messageKeyDataList.size() + " out of " + resultSize
+ " messages");
lastSearch.put("topicQueue", topicQueueSelect.getModelObject());
lastSearch.put("searchFields", searchFields);
lastSearch.put("from", from.getTime());
lastSearch.put("to", to.getTime());
lastSearch.put("maxResults", maxResults.getModelObject());
result.setList(messageKeyDataList);
target.add(feedback);
}
};
The SubmitLink does show me either the ResultView with the new list, or the info message, the IndicatingAjaxButton doesn't. I know the form submit is called, because the system.out is being printed.
Any suggestions on this?
SubmitLink is non-Ajax component. Using it will repaint the whole page!
IndicatingAjaxButton is an Ajax component. You need to use the passed AjaxRequestTarget to add components which should be repainted with the Ajax response. For example the FeedbackPanel should be added to the AjaxRequestTarget.
I found that I had to do setOutputMarkupPlaceholderTag(true) on both the resultContainer and the feedback. After that adding them to the requesttarget works as expected.

WP7 Textbox with title inside of textbox

I would like to have a textbox that lets a user enter some text (obviously). Let's say it's 'Title'. Is there a pre-built control that shows the name of the field (Title in this case) inside of the text box and then have it clear out when the user enter the field. Example: The search box at the top of this page has 'Search' but when you enter the box it goes away.
Watermarked TextBox
I think I remember it also being in the Mango Silverlight Toolkit too, correct me if I'm wrong:
Mango Silverlight Toolkit
This is an example. Put the GotFocus and LostFocus event in your textbox(in .xaml page).
<TextBox x:Name="UrlTextBox" Text="Search" Margin="0,0,98,0" GotFocus="UrlTextBox_GotFocus" LostFocus="UrlTextBox_LostFocus"/>
In xaml.cs page, add the following codes-
private void UrlTextBox_GotFocus(object sender, RoutedEventArgs e)
{
if (UrlTextBox.Text == "Search")
{
UrlTextBox.Text = "";
SolidColorBrush Brush1 = new SolidColorBrush();
Brush1.Color = Colors.Gray;
UrlTextBox.Foreground = Brush1;
}
else
{
char[] strDataAsChars = UrlTextBox.Text.ToCharArray();
int i = 0;
for (i = UrlTextBox.SelectionStart - 1; ((i >= 0) &&
(strDataAsChars[i] != ' ')); --i) ;
int selBegin = i + 1;
for (i = UrlTextBox.SelectionStart; ((i < strDataAsChars.Length) &&
(strDataAsChars[i] != ' ')); ++i) ;
int selEnd = i;
UrlTextBox.Select(selBegin, selEnd - selBegin);
}
}
private void UrlTextBox_LostFocus(object sender, RoutedEventArgs e)
{
if (UrlTextBox.Text == String.Empty)
{
UrlTextBox.Text = "Search";
SolidColorBrush Brush2 = new SolidColorBrush();
Brush2.Color = Colors.Gray;
UrlTextBox.Foreground = Brush2;
}
}

Pivot control dynamically adding pivot items throws ArgumentException was unhandled when select a index of pivot

i have a problem to add pivot item in pivot control ..i want to add pivot item in pivot(Mycontrol) when i add next button .code for next button
static int selectitem;
private void nextbuttonOnclick(object sender, RoutedEventArgs e)
{
if (selectitem != list.Count() - 1)
select(selectitem + 1);
else
{
select(0);
}
}
now it call the select method to add pivot item to pivot
void select(int i)
{
MyControl.Items.Clear();
pivotItem = new PivotItem();
Grid sta = new Grid();
WebBrowser wb = new WebBrowser();
sta.Background = new SolidColorBrush(Colors.White);
var address = "<h3>" + list.ElementAt(i).header + "</h3>" + "<br>" + "<img width=\"949\" height=\"449\" src=" + list.ElementAt(i).Imagee + " >" + "<br>" + list.ElementAt(i).Detail.ToString();
var ByteData = Encoding.UTF8.GetBytes(address);
System.Text.Encoding enc = System.Text.Encoding.UTF8;
string myString = enc.GetString(ByteData, 0, ByteData.Length);
try
{
wb.Loaded += (sendr, ev) =>
{
wb.NavigateToString(myString);
};
}
catch (Exception ex)
{
}
wb.Margin = new Thickness(0, 0, 0, 0);
sta.Children.Add(wb);
pivotItem.Content = sta;
MyControl.Items.Add(pivotItem);
try
{
if (i == -1)
MyControl.SelectedIndex = 0;
else
{
selectitem = i;
MyControl.SelectedIndex = i;
}
}
catch (IndexOutOfRangeException v)
{
}
}
but after adding one it shows a exception ie ArgumentException was unhandled
...thanx in advance
The ArgumentException is happening because of this line:
MyControl.Items.Clear();
That line removes all the items in the pivot control, but your internal selectitem variable doesn't account for that. In your code, there will always be only one pivot item (which sort of defeats the purpose of the pivot control). When you go to add item #2, the selectitem variable is set to 1 and the line MyControl.SelectedIndex = 1; cases the exception since there is only 1 pivot item (0 based arrays, and all that stuff).
Try removing the line that clears the pivot items above and see if it works for you. Otherwise, you're going to have to change the MyControl.SelectedIndex = i; line to be MyControl.SelectedIndex = 0;.
Just FYI - when I ran your sample, I needed to initialize selecitem to -1, not 0, or I got the same error message. I also added code to set the PivotItem.Header property to something so it was easier to flip between pivot items.
Just out of curiosity, why are you not doing this through DataBinding instead of all this code to load up items manually?

Resources