Reputation: 6368
I want to know which event is fired when ListBoxItems are added to the ListBox. Please take a note that I don't want an event when data changes. I want the event when control is added.
I have refered to this answer where they say use CollectionChaged Event It fires when Collection changes. So I cannot use that as that fires before the controls are added to the VisualTree.
You might be thinking why I need that. I simply want to change the width of the listbox to the widest item's width. If you are interested more in what I am trying to achieve then please have a look at my code:
private void SomeEvent(object sender, ............... e)
{
double greatestWidth = 0;
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(sidebar) - 1; i++)
{
ListBoxItem li = VisualTreeHelper.GetChild(sidebar, i) as ListBoxItem;
li.HorizontalAlignment = HorizontalAlignment.Center;
}
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(sidebar) - 1; i++)
{
ListBoxItem li = VisualTreeHelper.GetChild(sidebar, i) as ListBoxItem;
if (li.Width > greatestWidth)
{
greatestWidth = li.Width;
}
}
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(sidebar) - 1; i++)
{
ListBoxItem li = VisualTreeHelper.GetChild(sidebar, i) as ListBoxItem;
li.HorizontalAlignment = HorizontalAlignment.Stretch;
}
}
Update:
class ResizablePanel : StackPanel
{
protected override Size MeasureOverride(Size constraint)
{
Size calculatedSize = base.MeasureOverride(constraint);
foreach (ListBoxItem li in this.Children)
{
li.HorizontalAlignment = HorizontalAlignment.Center;
}
double greatestWidth = 0;
foreach (ListBoxItem li in this.Children)
{
if (li.Width > greatestWidth)
{
greatestWidth = li.Width;
}
}
foreach (ListBoxItem li in this.Children)
{
li.HorizontalAlignment = HorizontalAlignment.Stretch;
}
calculatedSize = new Size(greatestWidth, calculatedSize.Height);
return calculatedSize;
}
}
Upvotes: 3
Views: 227
Reputation: 13669
as discussed here is how you can take control over most of the sizing aspects
start by defining a new panel and override the method MeasureOverride
namespace CSharpWPF
{
class MyPanel : StackPanel
{
protected override Size MeasureOverride(Size constraint)
{
Size calculatedSize = base.MeasureOverride(constraint);
foreach (ListBoxItem item in this.Children)
{
//your logic with each item
}
return calculatedSize;
}
}
}
MeasureOverride method will be invoked whenever any item is added or removed or a change in layout is required i.e. resizing the container.
foreach (ListBoxItem item in this.Children)
is with assumption that you are going to use with ListBox only. You may change the same as desired.
then use this new panel as
<ListBox xmlns:l="clr-namespace:CSharpWPF">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<l:MyPanel />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
with this approach you can control the sizing much efficiently
read more on FrameworkElement.MeasureOverride
after looking at the sample here are the changes you need to do to get the desired
set the Margin="10,5,10,5"
to sidebar ListBox
add HorizontalAlignment="Right"
to sidebar ListBox
remove HorizontalAlignment="Center"
from ContentPresenter in metro.xaml line 35
set <Setter Property="HorizontalAlignment" Value="Stretch" />
metro.xaml line 51
add <Setter Property="TextBlock.TextAlignment" Value="Right" />
at line 52
Upvotes: 3
Reputation: 12295
You can listen to Items CollectionChanged like
public Window1()
{
InitializeComponent();
((INotifyCollectionChanged)mylistbox.Items).CollectionChanged += myListBox_CollectionChanged;
}
private void myListBox_CollectionChanged(object sender,NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Add)
{
foreach (var item in e.NewItems)
{
}
}
}
Plus here you will get the items directly instead of using VisualTreeHelper
Upvotes: 0