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
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;
}
}
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.
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);
}
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?
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.