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;
    }
}

      

+3


source to share


2 answers


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

+3


source


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

0


source







All Articles