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.
Related
I have an arraylist of all a bunch of winform controls (textboxes, checkboxes, radio buttons, etc).
I am trying to enable/disable them all at once.
Code is as below:
Button button = new Button();
Label label = new Label();
Listview listview = new ListView();
ArrayList controlList = new ArrayList();
controlList.add(button);
controlList.add(label);
controlList.add(listview);
foreach(object o in controlList) {
o.enabled = false;
}
But of course, this wouldn't work, since the class object does not have the property "enabled" in it.
What should I do to make this work?
You should use a List<Control>. This is the base class of all System.Windows.Controls. You can iterate over all properties of the Control type:
Button button = new Button();
Label label = new Label();
Listview listview = new ListView();
var controlList = new List<Control>();
controlList.Add(button);
controlList.Add(label);
controlList.Add(listview);
foreach(var o in controlList) {
o.Enabled = false;
}
Change:
o.enabled = false;
To
(o as Control.enabled = false;
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;
}
}
}
I am working on silverlight using c#. I have to display the combo items in a scrollbar.
My attempt to do this is:
TextBlock txtblkName = generateTextBlock();
ComboBox cb = new ComboBox();
ScrollViewer scrollViewer = new ScrollViewer();
cb.Width = 45;
cb.Height = 20;
foreach (String item in param.Component.Attributes.Items)
cb.ItemsSource = param.Component.Attributes.Items;
scrollViewer.Content = cb;
scrollViewer.HorizontalAlignment = HorizontalAlignment.Center;
scrollViewer.VerticalAlignment = VerticalAlignment.Center;
scrollViewer.ScrollToVerticalOffset(3);
cb.SelectionChanged += (o, e) =>
{
txtblkName.Text = cb.SelectedValue.ToString() + " " + param.Unit;
};
cb.SelectedIndex = param.Component.Attributes.Selected != -1 ? param.Component.Attributes.Selected : 0;
Grid.SetColumn(scrollViewer, 1);
childGrid.Children.Add(scrollViewer);
which results in scroll over combo box .Like this:
Not on it's item displayed by scrollbar.
Could some one please help me to create scrollbar only on items displayed not on all combo box?
You dont need ScrollViewer here, If you need Scrollbar for your comboboxItems set this property MaxDropDownHeight to some value
ComboBox cb = new ComboBox();
List<string> items = new List<string>();
items.Add("1");
items.Add("2");
items.Add("3");
items.Add("5");
items.Add("7");
items.Add("8");
cb.ItemsSource = items;
cb.MaxDropDownHeight = 20;
childGrid.Children.Add(cb);
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(..)
I have the following code where a click event will dynamically create additional Canvas to the WrapPanel, and each Canvas contains a TextBox and a Button. Once the Button on one Canvas is click, TextBox.Text and Button.Content change from "Foo" to "Jesus".
The below code works, but it's not ideal. Because each property Change ("Foo" to "Jesus), I have to run a loop. I have to run two loops just to change the text on the TextBox and Button. Is there a direct way to change the Properties other then a Loop? My actually application contains 30+ controls in a Canvas, I don't want to run 30+ loops each time just to change some text.
List<Canvas> cvList = new List<Canvas>();
List<TextBox> tbList = new List<TextBox>();
List<Button> FooList = new List<Button>();
WrapPanel wp = new WrapPanel();
private void createbtn1_Click(object sender, RoutedEventArgs e)
{
Canvas cv = new Canvas();
StackPanel sp = new StackPanel();
TextBox tb = new TextBox();
Button Foo = new Button();
sp.Orientation = Orientation.Vertical;
sp.Children.Add(tb);
sp.Children.Add(Foo);
cv.Children.Add(sp);
wp.Children.Add(cv);
cvList.Add(cv);
tbList.Add(tb);
FooList.Add(Foo);
cv.Width = 100;
cv.Height = 100;
tb.Text = "#" + (cvList.IndexOf(cv)+1);
tb.Width = 50;
tb.Height = 30;
Foo.Content = "Foo";
Foo.Click += destroy_Click;
}
private void Foo_Click(object sender, RoutedEventArgs e)
{
Button b = sender as Button;
var bIndex = FooList.IndexOf(b);
foreach (TextBox t in tbList)
{
if (tbList.IndexOf(t) == bIndex)
{
t.Text = "Jesus";
}
}
foreach (Button f in FooList)
{
if (FooList.IndexOf(t) == bIndex)
{
t.Content = "Jesus";
}
}
}
Just access the text boxes by index and set the content of the button directly:
if(bIndex < tbList.Count && bIndex != -1)
tbList[bIndex].Text = "Jesus";
if(b != null && bIndex != -1)
b.Content = "Jesus";
why can't you just get the item at the index and set that items text:
tbList[bindex].Text="Jesus";
As for setting the buttons content, you already have the button from the click event, so just use that:
b.Content = "Jesus";
You current code just loops through each item in the list and gets the index of the item and sees if it is the index you want. Accessing by the indexer of the list directly will give you what you want.
You will probably want to do some error checking, but that is not currently done in your existing code either.
Some info on using indexers from MSDN