Event fired over control added to list
I want to know what event is being called when ListBoxItems are added to the ListBox. Please note that I do not want events when the data changes. I want an event when a control is added.
I am referring to this answer where they say it uses the CollectionChaged event that fires when the collection changes. So I cannot use this as it fires before the controls are added to the VisualTree.
You might be thinking why I need this. I just want to change the width of the list to the widest width of the element. If you are more interested in what I am trying to achieve, please see 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;
}
}
source to share
as discussed here, how you can take control of most aspects of size.
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;
}
}
}
The MeasureOverride method will be called whenever any element is added or removed, or a layout change is required, i.e. a resize of the container.
foreach (ListBoxItem item in this.Children)
is on the assumption that you are only going to use it with a ListBox. You can change the same as you.
then use this new panel like
<ListBox xmlns:l="clr-namespace:CSharpWPF">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<l:MyPanel />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
with this approach, you can effectively control the size
more about FrameworkElement.MeasureOverride
after seeing the example, here are the changes you need to make to get the desired
-
set
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" />
string metro.xaml 51 -
add
<Setter Property="TextBlock.TextAlignment" Value="Right" />
on line 52
source to share
You can listen to CollectionChanged items as
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 get the elements directly instead of using the VisualTreeHelper
source to share