How can I remove a dynamically created button? - c#

I want to remove all children of a StackPanel except for a Label, but I can't get it to
remove a dynamically created Button.
<StackPanel Name="myStackPanel">
<Label Name="myLabel">Label text</Label>
<TextBlock Name="myTextBlock">TextBlock text</TextBlock>
</StackPanel>
private void button1_Click(object sender, RoutedEventArgs e)
{
Button buttonX= new Button();
buttonX.Name = "ButtonInstall";
buttonX.Content = "Click Me";
buttonX.Width = 150;
buttonX.HorizontalAlignment = HorizontalAlignment.Left;
buttonX.Click += new RoutedEventHandler(buttonX_Click);
myStackPanel.Children.Add(buttonX);
}
private void button2_Click(object sender, RoutedEventArgs e)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(myStackPanel); i++)
{
Visual childVisual = (Visual)VisualTreeHelper.GetChild(myStackPanel, i);
string controlName = childVisual.GetValue(Control.NameProperty).ToString();
if (childVisual.GetType() != typeof(Label))
{
myStackPanel.Children.Remove((UIElement)childVisual);
}
}

For your example, it's not necessary to use the VisualTreeHelper:
List<UIElement> delItems=new List<UIElement>();
foreach(UIElement uiElement in myStackPanel.Children){
if(uiElement is Label) continue;
delItems.Add(uiElement);
}
foreach(UIElement delItem in delItems){
myStackPanel.Children.Remove(delItem);
}

Related

how to clear button color second click in flow layout panel c#

I have a lot of buttons in flow layout panel. I created these buttons programmatically.
But I didn't if click button its color will be light green after second click will be reset color. I wrote this handler for flow layout panel. How can I do second click will clear button color:
private void Form1_Load(object sender, EventArgs e)
{
StringBuilder sb = new StringBuilder();
sb.Append( "3 x coca cola 33 cl");
sb.Append(Environment.NewLine);
sb.Append("DIN");
sb.Append("\t\t");
sb.Append("200");
//button2.Text = sb.ToString();
string products = "30000|3;3110002;Cola;400;150;100;1;1000|3;3110003;Snickers;400;150;100;1;1000|3;3110004;NesttleCrunch;400;150;100;1;1000|3;3110005;Marlbora;400;150;100;1;1000|3;3110006;Orange;400;150;100;1;1000|3;3110007;Milk;400;150;100;1;1000|3;3110008;Water;400;150;100;1;1000|3;3110009;Banana;400;150;100;1;1000|3;3110010;Honey;400;150;100;1;1000|3;3110011;Beer;400;150;100;1;1000|3;3110012;Hazelnut;400;150;100;1;1000|3;3110013;RedBull;400;150;100;1;1000|3;3110014;ChewingGum;400;150;100;1;1000|3;3110015;Apple;400;150;100;1;1000";
string[] listproducts = products.Split('|');
lblAvaliablePoint.Text = listproducts[0];
for (int i = 1; i < listproducts.Count();i++ )
{
string[] perproduct = listproducts[i].Split(';');
Button newButton = new Button();
newButton.Size = new System.Drawing.Size(170, 87);
newButton.BackColor = Color.LightGray;
newButton.UseVisualStyleBackColor = false;
newButton.Tag =perproduct[1];
newButton.Text = perproduct[0] + "x" + perproduct[2];
newButton.Click += new EventHandler(ButtonClickHandler);
flowLayoutPanel1.Controls.Add(newButton);
}
flowLayoutPanel1.VerticalScroll.Maximum = flowLayoutPanel1.Height+40;
flowLayoutPanel1.VerticalScroll.LargeChange = 30;
}
public void ButtonClickHandler(Object sender,EventArgs e)
{
((Button)sender).BackColor = Color.LightGreen;
}
What about add simple if condition into button handler like this?
public void ButtonClickHandler(object sender, EventArgs e)
{
if (((Button)sender).BackColor == Color.LightGreen)
{
((Button)sender).BackColor = Color.White; // Your default color
}
else
{
((Button)sender).BackColor = Color.LightGreen;
}
}
Change your ButtonClickHandler
public void ButtonClickHandler(Object sender, EventArgs e)
{
var currentButton = ((Button)sender);
if(currentButton != null)
{
currentButton.BackColor = currentButton.BackColor == Color.LightGreen ? Color.LightGray : Color.LightGreen;
}
}

Drag And Drop Not Working In ScrollViewer

My problem is the drag and drop of border become not workin when I wrap the canvas inside the scrollviewer.
1200x1200 canvas put in the 500x500 scrollviewer. I want the canvas is scrollable (touch slide) in the scrollviewer. The drag and drop in canvas is working perfectly before I insert in the scrollviewer.
MainWindow.xaml
<Grid ClipToBounds="True">
<ScrollViewer Name="scbb" Width="500" Height="500" HorizontalScrollBarVisibility="Hidden"
VerticalScrollBarVisibility="Hidden" HorizontalAlignment="Left"
VerticalAlignment="Top" Background="LightBlue" ScrollViewer.CanContentScroll="True">
<Canvas x:Name="canvas" Width="1200" Height="1200"
MouseLeftButtonDown="CanvasMouseLeftButtonDown"
MouseLeftButtonUp="CanvasMouseLeftButtonUp"
MouseMove="CanvasMouseMove">
</Canvas>
</ScrollViewer>
<Button x:Name="btnEnable" Content="Enable" Height="50" Width="50" Margin="0,0,115,10" VerticalAlignment="Bottom"
HorizontalAlignment="Right" Click="btnEnable_Click"/>
<Button Content="Add Image" Width="100" Height="100" VerticalAlignment="Bottom"
HorizontalAlignment="Right" Click="AddButtonClick" Margin="0,0,10,10"/>
</Grid>
MainWindow.xaml.cs
private void AddButtonClick(object sender, RoutedEventArgs e)
{
int iNum = SETTING.GetTableRunningNumber();
var borderWrap = new Border();
borderWrap.Width = 100;
borderWrap.Height = 100;
borderWrap.Background = Brushes.Green;
var label1 = new Label();
label1.VerticalAlignment = VerticalAlignment.Center;
label1.HorizontalAlignment = HorizontalAlignment.Center;
label1.Content = "Table " + iNum.ToString();
label1.Name = "Table" + iNum.ToString();
label1.Foreground = Brushes.White;
label1.FontWeight = FontWeights.Bold;
borderWrap.Child = label1;
borderWrap.MouseDown += TableMouseDown;
Canvas.SetLeft(borderWrap, 10);
Canvas.SetTop(borderWrap, 10);
canvas.Children.Add(borderWrap);
iNum += 1;
SETTING.SetTableRunningNumber(iNum);
}
private Point mousePosition;
private Border draggedBorder;
private void TableMouseDown(object sender, MouseButtonEventArgs e)
{
if (!SETTING.GetEnableDrag())
{
var cLabel = e.Source as Label;
var bBorder = e.Source as Border;
if (cLabel != null)
{
MessageBox.Show(cLabel.Name.ToString());
}
}
}
private void CanvasMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (SETTING.GetEnableDrag())
{
var dBorder = e.Source as Border;
var cLabel = e.Source as Label;
if (dBorder == null)
{
dBorder = (Border)cLabel.Parent;
}
if (dBorder != null && canvas.CaptureMouse())
{
mousePosition = e.GetPosition(canvas);
draggedBorder = dBorder;
Panel.SetZIndex(draggedBorder, 1);
}
}
}
async Task PutTaskDelay100()
{
await Task.Delay(100);
}
private async void CanvasMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (SETTING.GetEnableDrag())
{
await PutTaskDelay100();
if (draggedBorder != null)
{
canvas.ReleaseMouseCapture();
Panel.SetZIndex(draggedBorder, 0);
draggedBorder = null;
}
}
}
private void CanvasMouseMove(object sender, MouseEventArgs e)
{
if (SETTING.GetEnableDrag())
{
double canvasSize = 1200;
if (draggedBorder != null)
{
var position = e.GetPosition(canvas);
var offset = position - mousePosition;
mousePosition = position;
double newTop = Canvas.GetTop(draggedBorder) + offset.Y;
double newLeft = Canvas.GetLeft(draggedBorder) + offset.X;
if (newTop < 0)
{
newTop = 0;
}
else if (newTop + draggedBorder.ActualWidth > canvasSize)
newTop = canvasSize - draggedBorder.ActualWidth;
if (newLeft < 0)
{
newLeft = 0;
}
else if (newLeft + draggedBorder.ActualWidth > canvasSize)
newLeft = canvasSize - draggedBorder.ActualWidth;
Canvas.SetLeft(draggedBorder, newLeft);
Canvas.SetTop(draggedBorder, newTop);
}
}
}
I had the problem months ago and solved it in the code behind with these additions.
After the InitializeComponent in the WindowMain.xaml.cs add:
public WindowMain()
{
InitializeComponent();
// your code, etc.
scrollViewer.AllowDrop = true;
scrollViewer.PreviewDragEnter += scrollViewer_PreviewDragEnter;
scrollViewer.PreviewDragOver += scrollViewer_PreviewDragOver;
scrollViewer.Drop += scrollViewer_Drop;
}
void scrollViewer_PreviewDragEnter(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
e.Effects = DragDropEffects.Copy;
}
else
{
e.Effects = DragDropEffects.None;
}
}
void scrollViewer_PreviewDragOver(object sender, DragEventArgs e)
{
e.Handled = true;
}
bool IsDataAvailable = false;
void scrollViewer_Drop(object sender, DragEventArgs e)
{
// Get data object
var dataObject = e.Data as DataObject;
// Check for file list
if (dataObject.ContainsFileDropList())
{
// Process file names
StringCollection fileNames = dataObject.GetFileDropList();
bool isIsDataAvailable = false;
try
{
var uri = new Uri(fileNames[0]);
BitmapSource imageSource = new BitmapImage(uri);
isIsDataAvailable = true;
}
catch (Exception error)
{
string errorMessage = error.ToString();
}
finally
{
IsDataAvailable = isIsDataAvailable;
}
}
}
My program just loads a dropped file from the explorer file list I drop on the ScrollViewer . The scbb.AllowDrop=true in the ScrollViewer has to be set. And the routines to handle basic drag and drop. Your code should work once the ScrollViewer allows dropping.

Adding dynamic buttons in WPF

I made code that creates buttons dynamically, but how to assign different function to each button?
for (int i = 0; i < Buttons.Count; i++)
{
Button newBtn = new Button();
newBtn.Content = Buttons[i];
newBtn.Name = "Button" + i.ToString();
newBtn.Height = 23;
stackPanel1.Children.Add(newBtn);
newBtn.Click += new RoutedEventHandler(newBtn_Click);
}
private void newBtn_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("Hello");
}
Now each button shows "Hello", but I wish it to be "Hello1", "Hello2"....ect.
if you could create a collection of objects with DelegateCommands or RelayCommand Property and DisplayName Property - you would just need a ItemsControl bind to this Collection and a DataTemplate for binding a button to Command and Text.
EDIT: just out of my head
public class MyCommandWrapper
{
public ICommand Command {get;set;}
public string DisplayName {get;set;}
}
in your viewmodel
public ObservableCollection<MyCommandWrapper> MyCommands {get;set;}
MyCommands.Add(new MyCommandWrapper(){Command = MyTestCommand1, DisplayName = "Test 1"};
...
in your xaml
<ItemsControl ItemsSource="{Binding MyCommands}">
<ItemsControl.Resources>
<DataTemplate DataType="{x:Type local:MyCommandWrapper}">
<Button Content="{Binding DisplayName}" Command="{Binding Command}"/>
</DataTemplate>
</ItemsControl.Resources>
</ItemsControl>
EDIT 2: if you need a new dynamic button - just add a new wrapper to your collection
for (int i = 0; i < Buttons.Count; i++)
{
Button newBtn = new Button();
newBtn.Content = Buttons[i];
newBtn.Height = 23;
newBtn.Tag=i;
stackPanel1.Children.Add(newBtn);
newBtn.Click += new RoutedEventHandler(newBtn_Click);
}
private void newBtn_Click(object sender, RoutedEventArgs e)
{
Button btn=sender as Button;
int i=(int)btn.Tag;
switch(i)
{
case 0: /*do something*/ break;
case 1: /*do something else*/ break;
default: /*do something by default*/ break;
}
}
Check the sender parameter of your newBtn_Click function. It should contain the instance of the button that was clicked. You can cast it to a button and check the name:
private void newBtn_Click(object sender, RoutedEventArgs e)
{
var btn = sender as Button;
if(btn != null)
{
MessageBox.Show(btn.Name);
}
}
If you don't want to check the Name property, you can also use the Tag property (http://msdn.microsoft.com/library/system.windows.frameworkelement.tag.aspx) to which you can assign an arbitrary object and check this later:
Button newBtn = new Button();
newBtn.Tag = i;
And later in the click handler:
private void newBtn_Click(object sender, RoutedEventArgs e)
{
var btn = sender as Button;
if(btn != null)
{
if(btn.Tag is int)
MessageBox.Show(String.Format("Hello{0}", btn.Tag));
}
}
I would prefer the solution with Tag because it's more safe than extracting something from a string.
newBtn.Click += new RoutedEventHandler((s,e) => MessageBox.Show("hallo"+((Button)s).Name);
private void newBtn_Click(object sender, RoutedEventArgs e)
{
var button = sender as Button;
var buttonNumber = button.Name.Remove(0, 6);
MessageBox.Show("Hello" + buttonNumber);
}

ListBox handling in wpf application in visual studio

I have 3 listboxes,3 texboxes,3buttons in my window ,when i enter data from listbox1 into the textbox1 and click button or enter then the other 2 listbox items of same index should appear on the other 2 textboxes.
this is the code written till now
private void Get_Click(object sender, RoutedEventArgs e)
{
int x = listbox1.SelectedIndex;
listbox2.SelectedIndex = x;
listbox3.SelectedIndex = x;
ListBoxItem lb1 = (listbox1.SelectedItem as ListBoxItem);
tb1.Text = lb1.Content.ToString();
ListBoxItem lb2 = (listbox2.SelectedItem as ListBoxItem);
tb2.Text = lb2.Content.ToString();
ListBoxItem lb3 = (listbox3.SelectedItem as ListBoxItem);
tb3.Text = lb3.Content.ToString();
}
private void Add_Click(object sender, RoutedEventArgs e)
{
int x = listbox1.SelectedIndex;
listbox2.SelectedIndex = x;
listbox3.SelectedIndex = x;
listbox1.Items.Add(tb1.Text);
listbox2.Items.Add(tb2.Text);
listbox3.Items.Add(tb3.Text);
}
private void Delete_Click(object sender, RoutedEventArgs e)
{
int x = listbox1.SelectedIndex;
listbox2.SelectedIndex = x;
listbox3.SelectedIndex = x;
listbox1.Items.RemoveAt(listbox1.Items.IndexOf(listbox1.SelectedItem));
listbox2.Items.RemoveAt(listbox2.Items.IndexOf(listbox2.SelectedItem));
listbox3.Items.RemoveAt(listbox3.Items.IndexOf(listbox3.SelectedItem));
}
It's not really clear what you're after, but I think you're trying to get the text in tb1 to be the driver instead of selecting from listbox1. I've added some simple code to the Get_Click event:
private void Get_Click(object sender, RoutedEventArgs e)
{
foreach (ListBoxItem lbi in listbox1.Items) //new code
{ //new code
if (lbi.Content.ToString() == tb1.Text) //new code
{ //new code
lbi.IsSelected = true; //new code
break; //new code
} //new code
} //new code
int x = listbox1.SelectedIndex;
listbox2.SelectedIndex = x;
listbox3.SelectedIndex = x;
//ListBoxItem lb1 = (listbox1.SelectedItem as ListBoxItem); //updated
//tb1.Text = lb1.Content.ToString(); //updated
ListBoxItem lb2 = (listbox2.SelectedItem as ListBoxItem);
tb2.Text = lb2.Content.ToString();
ListBoxItem lb3 = (listbox3.SelectedItem as ListBoxItem);
tb3.Text = lb3.Content.ToString();
}
Is this the kind of thing you're after?

Problem while attempting to change selected index of a tabControl

The problem i face is quite annoying.
I have a tabControl with the 2 tabItems(Home,Show)
The Home tab starts as Visible and Show as Hidden
In Home i have an image for which i handle the MouseLeftButtonDown event.
This event should change the visibility of Show TabItem and make it Selected.
At the code i have a tabControl.SelectedIndex = 1;
which forces the tabControl SelectionChangeEvent (which i use to change the foreground
of the Show and Home TabItems).
The problem i face is that instead of the focus to get passed to Show, it remains on Home.
I have no problem with the code, because at the last step of the SelectionChange event handler ,which is the last function that gets executed by my code, what i see in the ui is correct.
So what gets executed after that?
Can anybody help?
private void Main_clientImage_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
showMenu.Visibility = Visibility.Visible;
setTabSelected("showMenu");
}
public void setTabSelected(String name)
{
for (int i = 0; i tabControl.Items.Count ; i++)
{
TabItem item = tabControl.Items.GetItemAt(i) as TabItem;
if (item.Name.Equals(name))
{
selectedTab=i;
tabControl.SelectedIndex = i;
item.Foreground = new SolidColorBrush(Colors.Black);
}
else
{
item.Foreground = new SolidColorBrush(Colors.White);
}
}
}
private void tabControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
for (int i = 0; i tabControl.Items.Count; i++)
{
TabItem item = tabControl.Items.GetItemAt(i) as TabItem;
if (tabControl.SelectedIndex == i)
{
item.Foreground = new SolidColorBrush(Colors.Black);
}
else
{
item.Foreground = new SolidColorBrush(Colors.White);
}
}
}
//EDIT: I solved it by adding a simple e.Handler = true at MouseLeftButtonDown event.
Whats wrong with this thing???
I changed the SelectedItem of TabControl in a method
void open_Click(object sender, RoutedEventArgs e)
and did it from a <Button Click="open_Click" and from a <DataGrid MouseDoubleClick="open_Click".
Only by adding
e.Handled = true;
at the end of in method open_Click it worked for the MouseDoubleClick as Fotis mentioned in the question.
There is problem with your code.
private void Main_clientImage_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
showMenu.Visibility = Visibility.Visible;
homeMenu.Visibility = Visibility.Hidden;
setTabSelected("showMenu");
}
public void setTabSelected(String name)
{
for (int i = 0; i < tabControl.Items.Count; i++)
{
TabItem item = tabControl.Items.GetItemAt(i) as TabItem;
if (item.Header.Equals(name))
{
selectedTab = i;
item.IsSelected = true;
item.Foreground = new SolidColorBrush(Colors.Black);
}
else
{
item.Foreground = new SolidColorBrush(Colors.White);
}
}
}
private void tabControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
for (int i = 0; i < tabControl.Items.Count; i++)
{
TabItem item = tabControl.Items.GetItemAt(i) as TabItem;
if (tabControl.SelectedIndex == i)
{
item.Foreground = new SolidColorBrush(Colors.Black);
}
else
{
item.Foreground = new SolidColorBrush(Colors.White);
}
}
}
In the above code I am checking item.Header.Equals(name) and set item.IsSelected = true. Sometimes selectionindex doesn't work properly. The above code should address your problem.
After the SelectedItem property of the TabControl has changed, you need to make sure that SelectedItem.IsFocused = true. If not just use SelectedItem.Focus() right after you changed the SelectedItem property. It helped in my case.

Categories

Resources