C# StackPanel: Old Items Remain After Updating Values - c#

Hey there StackOverflow,
I am having an issue with a certain portion of my Windows Store app. This is initially what is displayed...
and this is what happens when the button is clicked
As you can see, the show more button and the original string is still present. I have tried making the "Show More" button update the TextBlock to a "" value and the "Show More" button is still there and clickable. I have also tried clearing the StackPanel and re-adding the items to no avail.
Here is the code I used to do this:
private async void Description_Loaded(object sender, RoutedEventArgs e)
{
await wiki;
if (wiki.Result.ContainsKey("real_name"))
{
TeamInfoTitle.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
TeamDescription.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
PopulateInfo(Description);
}
else if(wiki.Result.ContainsKey("current_members"))
{
CharacterInfoTitle.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
Description.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
PopulateInfo(TeamDescription);
}
}
void expand_Click(object sender, RoutedEventArgs e)
{
HyperlinkButton button = (HyperlinkButton)sender;
button.Content = "Show Less";
button.Click -= expand_Click;
button.Click += shrink_Click;
TextBlock text = (TextBlock)button.Tag;
text.Text = (string)text.Tag;
}
void shrink_Click(object sender, RoutedEventArgs e)
{
HyperlinkButton button = (HyperlinkButton)sender;
button.Content = "Show More";
button.Click -= shrink_Click;
button.Click += expand_Click;
TextBlock text = (TextBlock)button.Tag;
string item = (string)text.Tag;
text.Text = item.Substring(0, item.LastIndexOf(" ", 150, 15)) + "...";
}
private void PopulateInfo(Grid desc)
{
for (int i = 0; i < desc.RowDefinitions.Count; i++)
{
string value;
if (wiki.Result.TryGetValue((desc.Children[i] as TextBlock).Name, out value))
{
FrameworkElement now = new TextBlock() { Text = value, FontSize = 24, TextWrapping = TextWrapping.Wrap };
if (value.Length > 200)
{
TextBlock text = (TextBlock)now;
HyperlinkButton expand = new HyperlinkButton() { Content = "Show More", HorizontalAlignment = Windows.UI.Xaml.HorizontalAlignment.Right, VerticalAlignment = Windows.UI.Xaml.VerticalAlignment.Bottom };
expand.Tag = text;
expand.Click += expand_Click;
StackPanel stack = new StackPanel();
text.Tag = value;
text.Text = value.Substring(0, value.LastIndexOf(" ", 150)) + "...";
stack.Children.Add(text);
stack.Children.Add(expand);
now = stack;
}
Grid.SetRow(now, i);
Grid.SetColumn(now, 1);
now.Margin = new Thickness(0, 0, 0, 10);
desc.Children.Add(now);
}
else
desc.Children[i].Visibility = Windows.UI.Xaml.Visibility.Collapsed;
}
}
Any help would be greatly appreciated! Note: Description and TeamDescription are Grids defined in the XAML.

Turns out the XAML code was triggering the loaded event twice, thanks swistak for putting me on the right track!

Related

How do you find the tag of a TabItem from a button in the tabs header?

I am trying to make a system to add and remove tabs from a tab control. Tabs are added by selecting the last tab (added in another method but consists of a "+" as the header). The header of newly created tabs header is a grid composed of a text block and a button. When the button is clicked, it will run Close_Click. The code works great at removing the tab, although how do I get the tag of the tab that had its close button clicked?
private void TabControl_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
if (TabControl.SelectedIndex == TabControl.Items.Count - 1)
{
string tabName = "Tab" + (TabControl.Items.Count - 1);
string tabTag = RandomString(16);
Grid Grid = new Grid();
TextBlock TextBlock = new TextBlock()
{
Text = tabName
};
Button Button = new Button()
{
Content = "X",
Width = Double.NaN,
Height = Double.NaN,
Background = Brushes.Transparent,
BorderBrush = Brushes.Transparent
};
Button.Click += Close_Click;
Grid.ColumnDefinitions.Add(new ColumnDefinition());
Grid.ColumnDefinitions.Add(new ColumnDefinition());
Grid.Children.Add(TextBlock);
Grid.Children.Add(Button);
Grid.SetColumn(TextBlock, 0);
Grid.SetColumn(Button, 1);
TabItem newTabItem = new TabItem
{
Header = Grid,
Name = tabName,
Tag = tabTag
};
TabControl.Items.Insert(TabControl.Items.Count - 1, newTabItem);
Dispatcher.BeginInvoke((Action)(() => TabControl.SelectedIndex = TabControl.Items.Count - 2));
}
}
private void Close_Click(object sender, RoutedEventArgs e)
{
var target = (FrameworkElement)sender;
while (target is Grid == false)
{
target = (FrameworkElement)target.Parent;
}
var tabItem = (target as Grid).Parent;
if (TabControl.SelectedIndex == TabControl.Items.IndexOf(tabItem))
{
TabControl.SelectedIndex = TabControl.Items.IndexOf(tabItem) - 1;
}
TabControl.Items.Remove(tabItem);
}
how do I get the tag of the tab that had its close button clicked?
Cast tabItem in your Close_Click event handler:
private void Close_Click(object sender, RoutedEventArgs e)
{
var target = (FrameworkElement)sender;
while (target is Grid == false)
{
target = (FrameworkElement)target.Parent;
}
var tabItem = (target as Grid).Parent as TabItem;
string tag = tabItem.Tag as string;
if (TabControl.SelectedIndex == TabControl.Items.IndexOf(tabItem))
{
TabControl.SelectedIndex = TabControl.Items.IndexOf(tabItem) - 1;
}
TabControl.Items.Remove(tabItem);
}

Change background of a button when clicking another button

I am currently experimenting in WPF and just created a UniformGrid with 800 buttons which are created in a for loop. All buttons have their own names and share the same click event.
What I want to do now is the following: I want to click the first button (rect0) to change the color of this button and the next one (rect1).
I am totally stuck right now because everything I write into the click event refers to the button I clicked.
public MainWindow()
{
InitializeComponent();
for (int i = 0; i < 800; i++)
{
Button BTN_rect = new Button()
{
Name = "rect" + i,
Background = Brushes.White,
};
BTN_rect.Click += BTN_rect_Click;
Uniform.Children.Add(BTN_rect);
}
}
private void BTN_rect_Click(object sender, RoutedEventArgs e)
{
Button BTN_rect = sender as Button;
BTN_rect.Background = Brushes.Red;
MessageBox.Show(BTN_rect.Name);
}
There are a load of ways to do this.
I took a shortcut and put just 9 buttons in a stackpanel, otherwise the same.
public MainWindow()
{
InitializeComponent();
for (int i = 0; i < 8; i++)
{
Button BTN_rect = new Button()
{
Name = "rect" + i,
Content =Name,
Tag = i,
Background = Brushes.White,
};
BTN_rect.Click += BTN_rect_Click;
sp.Children.Add(BTN_rect);
}
}
private void BTN_rect_Click(object sender, RoutedEventArgs e)
{
Button current = sender as Button;
current.Background = Brushes.Red;
string targetName = $"rect{((int)current.Tag) + 1}";
Button nextButton = sp.Children.OfType<Button>().Where(x => x.Name == targetName).SingleOrDefault();
nextButton.Background = Brushes.Red;
}
Usually, you'd template data into repeated controls rather than add them in code, btw.

WPF SurfaceButton that drops down SurfaceScrollViewer on click

As the title says, I'd like to have a component whose base is SurfaceButton, and when clicked will drop down a SurfaceScrollViewer. I think I've made the proper first steps, but the SurfaceScrollViewer never becomes visible, nor does it seem to show in Blend's hierarchy. Am I accessing or initializing something incorrectly? I have multiple instances of SurfaceDropDown objects as children of a StackPanel, which is the content of another SurfaceScrollViewer. This parenting scroll viewer is aligned in a grid, which is why I set the heights and widths using the ActualHeight/Width properties.
public class SurfaceDropDown : SurfaceButton
{
public SurfaceScrollViewer scrollViewer;
private StackPanel stackPanel;
public SurfaceDropDown()
{
this.Click += OnClick;
scrollViewer = new SurfaceScrollViewer();
scrollViewer.Height = this.ActualHeight * 5.0;
scrollViewer.Width = this.ActualWidth;
scrollViewer.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;
scrollViewer.VerticalAlignment = System.Windows.VerticalAlignment.Center;
scrollViewer.HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled;
scrollViewer.VerticalScrollBarVisibility = ScrollBarVisibility.Auto;
stackPanel = new StackPanel();
for (int i = 0; i < 5; ++i)
{
Label label = new Label();
label.Content = "Label " + i.ToString();
stackPanel.Children.Add(label);
}
scrollViewer.Content = stackPanel;
scrollViewer.ScrollChanged += OnScroll;
this.AddChild(scrollViewer);
}
private void OnClick(object sender, RoutedEventArgs e)
{
scrollViewer.Visibility = scrollViewer.Visibility != Visibility.Visible ? Visibility.Visible : Visibility.Collapsed;
}
private void OnScroll(object sender, RoutedEventArgs e)
{
}
}
Any help and/or suggestions are greatly appreciated!

WPF: how to call method by setting tag of a dynamically created buttons

3 problems in my WPF(window phone) simple project. I have spent lot of time by solving it but no specific result found..
In my cs file I have Created bunch of dynamic buttons...I crated with for loop and set tags for each dynamic button.
My cs File code is here.
private void Grid_View_Btn_1_Click(object sender, System.Windows.RoutedEventArgs e)
{
//Grid ButtonsAddition
Dispatcher.BeginInvoke(() =>
{
string[] Trade = new string[] { "Portfolio Display", "Trade Idea Entry", "Trade Idea Monitor", "Historical Performance", "Intraday Performance", "Stock Performance" };
StackPanel panel = new StackPanel();
panel.Orientation = System.Windows.Controls.Orientation.Vertical;
//panel.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
//panel.VerticalAlignment = System.Windows.VerticalAlignment.Top;
int i;
for (i = 0; i < Trade.Length; i++)
{
Button btn = new Button() { Content = Trade[i] };
btn.Margin = new Thickness(0, -10, 0, -10);
var brush = new ImageBrush();
brush.ImageSource = new BitmapImage(new Uri("C:/Users/HafizArslan/Documents/Visual Studio 2012/Projects/AimPass/AimPass/Images/tabbar_btn_blue.png", UriKind.Relative));
btn.Background = brush;
btn.Width = 190;
btn.Height = 75;
btn.FontSize = 14;
btn.FontWeight = light;
btn.FontStretch = Fill;
btn.HorizontalAlignment = HorizontalAlignment.Center;
btn.VerticalAlignment = System.Windows.VerticalAlignment.Stretch;
// btn.CornerRadius = new CornerRadius(15);
btn.BorderThickness = new Thickness(1, 1, 1, 1);
btn.Tag = i.ToString();
btn.Click += new RoutedEventHandler(abc_click);
panel.Children.Add(btn);
}
grid.Children.Add(panel);
});
}
private void abc_click(object sender, EventArgs e)
{
}
There are 6 buttons creted.
the problem is I want to perform different actions with button...I have set Tags but I dont know how can I access an actions with buttons Tag..?
I mean I want something like this...!!
private void abc_click(object sender, EventArgs e)
{
// If(btn.Tag==1)
{
//Some Code Here
}
else
if(btn.Tag==2) {
//Perform other Function
}
} Etc.....?
and other problem is I have made a image brush..Assign exact path of image...for every created button background....But Image is not attached...
Kindly tell me about these 2 problems...
You have sender in handler, you can type cast sender to button and access Tag property from it:
private void abc_click(object sender, EventArgs e)
{
Button button = (Button)sender;
if(Convert.ToInt32(button.Tag) == 1)
{
.....
}
}
In your for loop, you can associate handler to the button.
Such as:
Button btn = new Button() { Content = Trade[i] };
btn.Margin = new Thickness(0, -10, 0, -10);
if(<something>)
btn.Click += YourEventHandler1;
if(<something2>)
btn.Click += YourEventHandler2;
If you want to access tag property, you need to cast the sender to Button, as so:
private void abc_click(object sender, EventArgs e)
{
var btn = (Button)sender;
}
you should go with this
var tag=((sender as Button).Tag).ToString();
////now use a switch
Switch(tag)
{
case "1":
//Action
break;
case "2":
//Acrion
break;
//more cases
}
hope this helps.
if for all created buttons the event is same then One approach could be to get the tag in the event like this
int tag=Convert.ToInt32((sender as Button).Tag);
now use a switch
switch(tag)
{
case 1:
//Action
break;
case 2:
//Acrion
break;
//more cases
}
hope this helps.

Unable to update Label in prompt box

I am working on the following code:
private Label textLabel;
public void ShowDialog()
{
Form prompt = new Form();
prompt.Width = 500;
prompt.Height = 150;
prompt.Text = caption;
textLabel = new Label() { Left = 50, Top=20, Text="txt"};
TextBox textBox = new TextBox() { Left = 50, Top=50, Width=400 };
Button confirmation = new Button() { Text = "Ok", Left=350, Width=100, Top=70 };
confirmation.Click += (sender, e) => { prompt.Close(); };
prompt.Controls.Add(confirmation);
prompt.Controls.Add(textLabel);
prompt.Controls.Add(textBox);
prompt.ShowDialog();
}
I am calling the above method using another method and trying to update the textLabel field inside a loop like this
public void doIt()
{
ShowDialog();
for(int i=0;i<10;i++)
{
textLabel.TEXT = ""+i;
Threading.Thread.Sleep(1000);
}
}
That is the way we do in Java, but in C# it I could not update the label text in this way. What is wrong here and why can't I update the text?
So this is how I would do it, it is not a complete solution but I hope it will point you in the right direction:
Make the Prompt class that will derive from the Form. Add the controls to it (I did it manually but you could use the designer). Add the Timer which will be triggered on each second and which will change the label's text. When the counter hits 10 stop the timer.
public partial class Prompt : Form
{
Timer timer;
Label textLabel;
TextBox textBox;
Button confirmation;
int count = 0;
public Prompt()
{
InitializeComponent();
this.Load += Prompt_Load;
this.Width = 500;
this.Height = 150;
textLabel = new Label() { Left = 50, Top = 20, Text = "txt" };
textBox = new TextBox() { Left = 50, Top = 50, Width = 400 };
confirmation = new Button() { Text = "Ok", Left = 350, Width = 100, Top = 70 };
this.Controls.Add(confirmation);
this.Controls.Add(textLabel);
this.Controls.Add(textBox);
timer = new Timer();
timer.Interval = 1000;
timer.Tick += timer_Tick;
}
void Prompt_Load(object sender, EventArgs e)
{
timer.Start();
}
void timer_Tick(object sender, EventArgs e)
{
this.textLabel.Text = " " + count.ToString();
count++;
if (count == 10)
timer.Stop();
}
}
In the doIt method, create the instance of your Prompt form, set its caption and call its ShowDialog() method.
public void doIt()
{
Prompt p = new Prompt();
p.Text = caption;
p.ShowDialog();
}

Categories

Resources