Vishal
Vishal

Reputation: 6368

event fired on control added to the listbox

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

Answers (2)

pushpraj
pushpraj

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

yo chauhan
yo chauhan

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

Related Questions