user3557327
user3557327

Reputation: 1169

Obtain DataGrid inside ItemsControl from the binded item

I have an ItemsControl that uses DataGrid in its template like this:

<ItemsControl Name="icDists" ItemsSource="{Binding Dists}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <DataGrid ItemsSource="{Binding}" Width="150" Margin="5" AutoGenerateColumns="False" IsReadOnly="True">
                <DataGrid.Columns>
                    <DataGridTextColumn Header="Key" Binding="{Binding Key}" Width="1*" />
                    <DataGridTextColumn Header="Value" Binding="{Binding Value}" Width="1*" />
                </DataGrid.Columns>
            </DataGrid>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

The ItemsControl is binded to a Dists property in my model that looks like this:

ObservableCollection<Dictionary<string, string>> Dists;

How can I obtain the DataGrid that corresponds to an item in the Dists property? I've tried with this code, which gives me a ContentPresenter but I don't know how to obtain the DataGrid from it:

var d = Dists[i];
var uiElement = (UIElement)icDistribucion.ItemContainerGenerator.ContainerFromItem(d);

I've tried walking up the tree with VisualHelper.GetParent but couldn't find the DataGrid.

Upvotes: 1

Views: 927

Answers (1)

Chubosaurus Software
Chubosaurus Software

Reputation: 8161

Need to search the VisualTree if you want to do something like that. Though I recommend reading a bit more on MVVM patterns. But here is what you want.


using System.Windows.Media;

private T FindFirstElementInVisualTree<T>(DependencyObject parentElement) where T : DependencyObject
{
    var count = VisualTreeHelper.GetChildrenCount(parentElement);
    if (count == 0)
        return null;

    for (int i = 0; i < count; i++)
    {
        var child = VisualTreeHelper.GetChild(parentElement, i);

        if (child != null && child is T)
        {
            return (T)child;
        }
        else
        {
            var result = FindFirstElementInVisualTree<T>(child);
            if (result != null)
                return result;
        }
    }
    return null;
}

Now after you set your ItemsSource and the ItemControl is ready. I'm just going to do this in the Loaded event.

private void icDists_Loaded(object sender, RoutedEventArgs e)
{
    // get the container for the first index
    var item = this.icDists.ItemContainerGenerator.ContainerFromIndex(0);
    // var item = this.icDists.ItemContainerGenerator.ContainerFromItem(item_object); // you can also get it from an item if you pass the item in the ItemsSource correctly

    // find the DataGrid for the first container
    DataGrid dg = FindFirstElementInVisualTree<DataGrid>(item);

    // at this point dg should be the DataGrid of the first item in your list

}

Upvotes: 1

Related Questions