WPF C# Get text from a Textblock inside a ListBoxItem - c#

How can i access a Textblock inside a Stackpanel that is inside a ListBoxItem?
For example:
ListBoxItem MyItem = new ListBoxItem();
StackPanel StackPnl = new StackPanel();
TextBlock Title = new TextBlock();
Title.Text = "Item 1";
StackPnl.Children.Add(Title);
MyItem.Content = StackPnl;
How can i later access the Text property of that Textblock with Listbox.SelectedItem?

Try this:
//listBox1 is your ListBox
ListBoxItem MyItem = listBox1.SelectedItem as ListBoxItem;
if(MyItem != null)
{
StackPanel sp = MyItem.Content as StackPanel;
if(sp != null && sp.Children.Count > 0)
{
TextBlock textBlock = sp.Children[0] as TextBlock;
if(textBlock != null)
{
string text = textBlock.Text;
}
}
}

Related

Sorting List with Custom Control

I want to sort a list that contains custom control.
The list has a list of listboxitem that have content with a checkbox inside, and the checkbox has a textblock inside.
List<ListBoxItem> listboxItem =new List<ListBoxItem>();
Some code that add the control into listboxItem with for loop
{
ListBoxItem lbi = new ListBoxItem();
CheckBox chkBox = new CheckBox();
TextBlock txtBlock = new TextBlock();
txtBlock.Text = sometext;
chkBox.Content = txtBlock;
lbi.Content = chkBox;
listBoxItems.Add(lbi);
}
listboxItems.Sort();
And I have implement IComparable interface
public int CompareTo(Object obj)
{
if (obj == null) return 1;
List<ListBoxItem> listBoxItems = obj as List<ListBoxItem>;
for (int i = 0; i < listBoxItems.Count; i++)
{
if (i < listBoxItems.Count)
{
ListBoxItem listBoxItem = listBoxItems[i];
ListBoxItem lbi = this.listBoxItems[i];
CheckBox checkBox = listBoxItem.Content as CheckBox;
CheckBox chk = lbi.Content as CheckBox;
TextBlock textBlock = checkBox.Content as TextBlock;
TextBlock txt = chk.Content as TextBlock;
return string.Compare(txt.Text, textBlock.Text);
}
}
return 0;
}
And it still give me error that need to implement Icomparable.
Not sure is it implement or use correctly, pretty new to me for this implementation #.#
Just found out that can use Linq and Tag to get rid of IComparable.
Edited Code:
Some code that add the control into listboxItem with for loop
{
ListBoxItem lbi = new ListBoxItem();
CheckBox chkBox = new CheckBox();
TextBlock txtBlock = new TextBlock();
txtBlock.Text = sometext;
chkBox.Content = txtBlock;
lbi.Content = chkBox;
lbi.Tag = sometext;
listBoxItems.Add(lbi);
}
listBoxItems = listBoxItems.OrderBy(x => x.Tag).ToList();
Then, the list will be sort in alphabetic perfectly.

Get the Parent node and Child node of selected items in WPF C# TreeView

I used this code to fill a treeview.
How can get all parent nodes and child node and root?
(visual studio 2017 WPF)
example
private TreeViewItem GetTreeView(string text, string imagePath)
{ TreeViewItem item = new TreeViewItem();
item.IsExpanded = true;
// create stack panel
StackPanel stack = new StackPanel();
stack.Orientation = Orientation.Horizontal;
// create Image
Image image = new Image();
image.Source = new BitmapImage(new ri("pack://application:,,/Image/" +
imagePath));
// Label
Label lbl = new Label();
lbl.Content = text;
lbl.Content = text;
// Add into stack
stack.Children.Add(image);
stack.Children.Add(lbl);
// assign stack to header
item.Header = stack;
return item;
}
I tried this code, it works for get the index but I can not take the nodes (parent)
var tree = sender as TreeView;
if (tree.SelectedValue != null)
{
index++;
TreeViewItem itemLvl = tree.SelectedItem as TreeViewItem;
ItemsControl parent = ItemsControl.ItemsControlFromItemContainer(itemLvl);
while (parent != null && parent.GetType() == typeof(TreeViewItem))
{
index++;
parent = ItemsControl.ItemsControlFromItemContainer(parent);
//var sp = ?????.Header as StackPanel;
//var tb = sp.Children[1] as Label;
//var im = sp.Children[0] as Image;
//string test= sp.Children[1].ToString();
}
Thanks for your help
in generally your idea is correct.
code you need will be looks like:
private void TvMain_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
string result = "";
TreeView tree = (TreeView) sender;
TreeViewItem item = (TreeViewItem) tree.SelectedItem;
result = item.Header.ToString();
while (item.Parent != null && item.Parent is TreeViewItem)
{
item = (TreeViewItem)item.Parent;
result = item.Header.ToString() + " \\ " + result;
}
MessageBox.Show(result);
}
result will be:
full demo project available on https://github.com/KohrAhr/Q54482751

How to programmatically change selected tabItem Header colour from code behind

I have a program in which I have to load colours at startup.
Then I have to add a tabcontrol with tab items:
TabControl tabc = m_Executer.GetTabControl();<---- from outside
if (tabc != null)
{
TabItem tbi = new TabItem();
tbi.Header.Background = Brushes.Transparent;
tbi.Header.Content = "End manager";
tabc.Items.Add(tbi);
tabc.SelectionChanged += (sender2, args) =>
{
((TabItem)(tabc.SelectedItem)).Background = Brushes.Red;
tabc.UpdateLayout();
};
}
the idea is changing the background when the selectionchanged event is fired but that doesn't work.
The default control template for a TabItem contains two Border elements named "mainBorder" and an "innerBorder". You could change the Background of the latter one:
tabc.SelectionChanged += (sender2, args) =>
{
if(args.AddedItems != null && args.AddedItems.Count > 0)
{
TabItem ti = args.AddedItems[0] as TabItem;
if(ti != null && VisualTreeHelper.GetChildrenCount(ti) > 0)
{
Grid grid = VisualTreeHelper.GetChild(ti, 0) as Grid;
if (grid != null)
{
Border mainBorder = grid.Children[0] as Border;
if (mainBorder != null)
{
Border innerBorder = mainBorder.Child as Border;
if(innerBorder != null)
innerBorder.Background = Brushes.Red;
}
}
}
}
};
The above code works on Windows 10. The templates may differ between different versions of Windows.
If you want to change the background of the unselected TabItem you simply replace AddedItems with RemovedItems and set the Background property of the mainBorder.
You might use a textblock to change color:
TabItem tbi = new TabItem();
tbi.Header = Brushes.Transparent;
TextBlock tbk = new TextBlock() { Text="End manager" };
tbi.Header = tbk;
tabc.Items.Add(tbi);
and then change the textblock on the event
tabc.SelectionChanged += (sender2, args) =>
{
((TabItem)(tabc.SelectedItem)).Foreground = Brushes.Red;
tabc.UpdateLayout();
};
EDIT you'd better de-highlight the unselected items:
tabc.SelectionChanged += (sender2, args) =>
{
foreach (var item in tabc.Items)
{
if (item == ((TabItem)(tabc.SelectedItem)))
((TabItem)item).Foreground = Brushes.Red;
else
((TabItem)item).Foreground = Brushes.Black;
}
};
You have to set the Content to TextBlock instead of a string:
XAML:
<TabControl>
<TabControl.Items>
<TabItem >
<TabItem.Header>
<TextBlock Background="Red" Text="Foo"/>
</TabItem.Header>
</TabItem>
<TabItem Header="Bar" />
</TabControl.Items>
</TabControl>
or code behind (for whatever reason...)
TabItem tbi = new TabItem();
TextBlock headerElement = new TextBlock();
headerElement.Text = "End manager";
headerElement.Background = Brushes.Red;
tbi.Header = headerElement;
I also suggest you do take a deep dive into the MVVM pattern. In 98% of the cases it's best practice to write your UIs in XAML and bind to a ViewModel.
BTW: Your code doesn't even compile as Headeris of type object...

Change Foreground item of ListView

I want to change the Foreground of a item on a ListView of my UWP.
I am using:
int i_DeleteRow = ListView1.SelectedIndex;
var item = ListView1.Items[i_DeleteRow] as ListViewItem;
if (item != null)
{
item.Foreground = new SolidColorBrush(Colors.Red);
}
But with this code item is always null.
Any help is appreciated.
You need to use ItemContainerGenerator.ContainerFromIndex. It returns a DependencyObject then you can cast it to ListBoxItem and use the ListBoxItem's properties like Foreground:
ListViewItem item = (ListViewItem)(ListView1.ItemContainerGenerator.ContainerFromIndex(ListView1.SelectedIndex));
if (item != null)
{
item.Foreground = new SolidColorBrush(Colors.Red);
}

How to select an item from a ListBox without using SelectionChange event

I am Silverlight developer and coding in C# to select an item from a list and display the selected item in the textBlock nearby.
My code to do so is:
ListBox lines = new ListBox();
TextBlock txtblkShowSelectedValue = new TextBlock();
ScrollViewer scrollViewer = new ScrollViewer();
scrollViewer.VerticalScrollBarVisibility = ScrollBarVisibility.Visible;
lines.ItemsSource = param.Component.Attributes.Items;
Grid.SetColumn(lines, 1);
Grid.SetRow(lines, LoopCount);
childGrid.Children.Add(lines);
lines.SelectedIndex = 0;
lines.SelectedItem = param.Component.Attributes.Items;
The problem is how to select a value and how to display it in textblock "txtblkShowSelectedValue " ? because I cannot declare textblock and List variable globally because of current condition if I use selectionChange event
EDIT: The current scenario is :(lines (List) is in different function so it's not in scope of List_SelectionChanged() function)
private static Grid GenerateList(Parameter param, int LoopCount, Grid g)
{
Grid childGrid = new Grid();
ColumnDefinition colDef1 = new ColumnDefinition();
ColumnDefinition colDef2 = new ColumnDefinition();
ColumnDefinition colDef3 = new ColumnDefinition();
childGrid.ColumnDefinitions.Add(colDef1);
childGrid.ColumnDefinitions.Add(colDef2);
childGrid.ColumnDefinitions.Add(colDef3);
TextBlock txtblk1ShowStatus = new TextBlock();
TextBlock txtblkLabel = new TextBlock();
ListBox lines = new ListBox();
ScrollViewer scrollViewer = new ScrollViewer();
scrollViewer.VerticalScrollBarVisibility = ScrollBarVisibility.Visible;
lines.ItemsSource = param.Component.Attributes.Items;
Grid.SetColumn(lines, 1);
Grid.SetRow(lines, LoopCount);
childGrid.Children.Add(lines);
lines.SelectedIndex = 0;
lines.SelectedItem = param.Component.Attributes.Items;
lines.SelectionChanged += new SelectionChangedEventHandler(List_SelectionChanged);
lines.SelectedIndex = lines.Items.Count - 1;
g.Children.Add(childGrid);
return (g);
}
static void List_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
MessageBox.Show("clist _SelectionChanged1");
TextBlock txtblk1ShowStatus = new TextBlock();
txtblk1ShowStatus.Text = lines[(sender as ListBox).SelectedIndex];
}
This could be streamlined, but should work as a quick 'n dirty example of one way to solve the problem...
void lb_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
Grid g = null;
ListBox lb = sender as ListBox;
if (lb != null && lb.SelectedIndex >= 0)
{
// Find the top-level grid
var parent = VisualTreeHelper.GetParent(lb);
while (parent != null)
{
if (parent.GetType() == typeof(Grid))
{
if ((parent as Grid).Name.Equals("LayoutRoot"))
{
g = (Grid)parent;
break;
}
}
parent = VisualTreeHelper.GetParent(parent);
}
// Found the LayoutRoot, find the textblock
if (g != null)
{
for (int i = 0; i < g.Children.Count; i++)
{
var child = VisualTreeHelper.GetChild(g, i);
if (child is TextBlock)
{
(child as TextBlock).Text = (string)lb.SelectedItem;
break;
}
}
}
}
}
You could also name your textblock and search for that (as I did for "LayoutRoot").
Obviously, this code assumes the textblock is a child of the top-level Grid. Implementing a recursive search wouldn't be difficult.
lines.SelectionChanged+=new System.EventHandler(this.UpdateTextBlock); // add selectionchanged even for your listbox;
private void UpdateTextBlock(object sender, SelectionChangedEventArgs e)
{
txtblkShowSelectedValue.Text=this.lines[(sender as Listbox).SelectedIndex].ToString(); // just edit the content of your texblock
}
EDIT : thank you, and sorry to be late :-)
try this :
add parameter for the function, as this :
lines.SelectionChanged += new SelectionChangedEventHandler(List_SelectionChanged)
change parameter of this function and set your textblock as this :
static void List_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
MessageBox.Show("clist _SelectionChanged1");
txtblkShowSelectedValue.Text=this.lines[(sender as Listbox).SelectedIndex].ToString()
}
Afteralli solved the problem like this:
lines.SelectionChanged += (o, e) =>
{
MessageBox.Show("clist _SelectionChanged1");
txtblk1ShowStatus.Text = lines.SelectedItem.ToString();
};
lines.SelectedIndex = lines.Items.Count - 1;
in my function GenerateList(..)

Categories