Why ItemContainerGenerator.ContainerFromIndex() returns null and how to avoid this behavior?

后端 未结 5 424
我在风中等你
我在风中等你 2020-12-06 16:31

I\'m using this snippet to analyze the rows I\'ve selected on a datagrid.

for (int i = 0; i < dgDetalle.Items.Count; i++)
{
    DataGridRow row = (DataGri         


        
相关标签:
5条回答
  • 2020-12-06 17:00

    Use this subscription:

    TheListBox.ItemContainerGenerator.StatusChanged += (sender, e) =>
    {
      TheListBox.Dispatcher.Invoke(() =>
      {
         var TheOne = TheListBox.ItemContainerGenerator.ContainerFromIndex(0) as ListBoxItem;
           if (TheOne != null)
             // Use The One
      });
    };
    
    0 讨论(0)
  • 2020-12-06 17:05

    Try this,

    DataGridRow row = (DataGridRow)grid.ItemContainerGenerator.ContainerFromIndex(index);
            if (row == null)
            {
                              grid.UpdateLayout();
                grid.ScrollIntoView(grid.Items[index]);
                row = (DataGridRow)grid.ItemContainerGenerator.ContainerFromIndex(index);
            }
    
    0 讨论(0)
  • 2020-12-06 17:05

    In my case grid.UpdateLayout(); didn't help an I needed a DoEvents() instead:

        DataGridRow row = (DataGridRow)grid.ItemContainerGenerator.ContainerFromIndex(index);
    
        if (row == null)
        {
    
            WPFTools.DoEvents();
    
            grid.ScrollIntoView(grid.Items[index]);
            row = (DataGridRow)grid.ItemContainerGenerator.ContainerFromIndex(index);
        }
    
    
        /// <summary>
        /// WPF DoEvents
        /// Source: https://stackoverflow.com/a/11899439/1574221
        /// </summary>
        public static void DoEvents()
        {
            var frame = new DispatcherFrame();
    
            Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background,
                new DispatcherOperationCallback(
                    delegate (object f)
                    {
                        ((DispatcherFrame)f).Continue = false;
                        return null;
                    }), frame);
    
            Dispatcher.PushFrame(frame);
        }
    
    0 讨论(0)
  • 2020-12-06 17:06

    In addition to other answers: items aren't available in constructor of the control class (page / window / etc).

    If you want to access them after created, use Loaded event:

    public partial class MyUserControl : UserControl
    {
        public MyUserControl(int[] values)
        {
            InitializeComponent();
    
            this.MyItemsControl.ItemsSource = values;
    
            Loaded += (s, e) =>
            {
                for (int i = 0; i < this.MyItemsControl.Items.Count; ++i)
                {
                    // this.MyItemsControl.ItemContainerGenerator.ContainerFromIndex(i)
                }
            };
        }
    }
    
    0 讨论(0)
  • 2020-12-06 17:18

    The DataGrid is virtualizing the items, the respective rows (i.e. containers) are only created when the row is in view.

    You could either turn off virtualization (which makes the first time loading very slow if you have many items, also the memory usage will be higher) or you just iterate over the data and check the values of the data objects' properties which should be bound to the data-grid. Usually you should not need the UI elements at all...

    0 讨论(0)
提交回复
热议问题