views:

1316

answers:

3

Hi all, I got a problem trying to find an element declared in DataTemplate, that after was applied like a ContentTemplate to TabItem object. I saw that there is already some solutions in regard of this problem, but no one of them actually works in my case, and I would like to understand why (obviously I make mistake in some place) Here is a sample code:

<DataTemplate x:Key="TabItemDataTemplate">             
    <Grid HorizontalAlignment="Stretch" 
        VerticalAlignment="Stretch" Name="templateGrid">
        <Grid.RowDefinitions>
            <RowDefinition Height="6.0*"> </RowDefinition>
            <RowDefinition Height="6" ></RowDefinition>
            <RowDefinition Height="6.0*" ></RowDefinition>
            <RowDefinition Height="*" ></RowDefinition>
        </Grid.RowDefinitions>                

        <ListView x:Name="repoView" Grid.Row="0" 
            VerticalAlignment="Stretch"
            ItemsSource="{Binding Source={StaticResource  DataProviderForListView}}">                        
            <GridView>
                <GridViewColumn Header="State"
                    DisplayMemberBinding="{Binding Path=RepositoryItemState}"/>
                <GridViewColumn Header="Working Copy Rev num."
                    DisplayMemberBinding="{Binding Path=WCRevision}"/>
                <GridViewColumn Header="Repository Rev num."
                    DisplayMemberBinding="{Binding Path=RepoRevision}"/>
                <GridViewColumn Header="User"
                    DisplayMemberBinding="{Binding Path=Account}"/>
                <GridViewColumn Header="Item"
                    DisplayMemberBinding="{Binding Path=ItemName}"/>
            </GridView>
        </ListView>

        <GridSplitter x:Name="gridSplitter" Grid.Row="1"
            ResizeDirection="Rows" Background="Gray" 
            Height="4" HorizontalAlignment="Stretch"
            Style="{StaticResource gridSplitterStyle}"/>

        <RichTextBox x:Name="rowView" Grid.Row="2" 
            BorderBrush="Bisque" VerticalAlignment="Stretch"
            IsReadOnly="True" Background="YellowGreen"
            FontFamily="Comic Sans Serif"/>


        <ToggleButton x:Name="rbWorkingCopy"
            Template="{StaticResource ToggleButtonControlTemplate}"
            Grid.Row="3" Width="100" Height="22"
            Content="{StaticResource WorkingCopyTitle}"
            HorizontalAlignment="Left" VerticalAlignment="Bottom"
            Command="repoManager:AppCommands.GetWorkingCopyInfoCommand" />
        <ToggleButton x:Name="rbRepository"
            Template="{StaticResource ToggleButtonControlTemplate}"
            Grid.Row="3"  Width="100" Height="22"
            Content="{StaticResource  RepositoryTitle}"
            HorizontalAlignment="Left"
            VerticalAlignment="Bottom"  Margin="120,0,0,0" 
            Command="repoManager:AppCommands.GetRepoInfoCommand" />
        <ProgressBar x:Name="checkRepositoryProgress" Grid.Row="3"
            Width="220" Height="22" HorizontalAlignment="Right"  
            VerticalAlignment="Bottom" Margin="250,0,10,0"
            IsIndeterminate="True"
            IsEnabled="{Binding repoManager:ExecutingCommand}"  />
    </Grid>
</DataTemplate>

This code is porgrammatically applied to the given TabItem object in following way :

this.ContentTemplate = FindResource("TabItemDataTemplate") as DataTemplate;

After I need access to the ListView element declared in DataTemplate, so I execute the codes found around in internet, and also on this site. Here is a short example:

/* Getting the ContentPresenter of myListBoxItem*/          
ContentPresenter myContentPresenter =
    FindVisualChild<ContentPresenter>(this);

// this.GetVisualChild(0)
/* Finding textBlock from the DataTemplate that is set on that ContentPresenter*/
DataTemplate myDataTemplate = myContentPresenter.ContentTemplate;

ListView repoListView = (ListView)myDataTemplate.FindName("repoView", 
    myContentPresenter);

Problem1: In this case ContentTemplate of ContentPresenter is Null, so code execution crashes. Prolem2: Ok, I think, may be I need to navigate throw TabItem content directly, so the code becomes, more or less:

/* Getting the ContentPresenter of myListBoxItem*/          
ContentPresenter myContentPresenter =
    FindVisualChild<ContentPresenter>(this);

// this.GetVisualChild(0)
/* Finding textBlock from the DataTemplate that is set on that ContentPresenter*/
DataTemplate myDataTemplate = this.ContentTemplate;

ListView repoListView = (ListView)myDataTemplate.FindName("repoView", 
    myContentPresenter);

this is TabItem object. But the strage things, that the ContentTemplate of this is completely different from that one assigned above. I'm sure that I missed something somewhere, can you help me to figure out the problem ? Thank you.

A: 

You don't want to use any of the template properties of the TabItem, since those are used to create the actual controls, rather than storing them. You should be able to search the visual tree for the ListView directly, rather than going through the DataTemplate.

Andy
Sure. I "resolve", may be, this problem, by calling in moment of assignment of ControlTemplate LoadContent(), that in my particular case returns the Grid, that is the root of my DataTemplate. My confusion was, why the ContentPresenter doesn't contain anything ? In sample codes found in internet there were no any explicit ContentPresenter declaration inside DataTemplate. At the end, I little bit change my code strucure, in order to acceess the data I need in other ways, my be also more simple:), by the way till now I didn't find the resolution of that kind of problem.
Tigran
One thing that I noticed, navigating throw the sample codes, that they usually applies the DataTemplate from Parent element to Item. So I tried to apply TabControl's ItemTemplate property (even if it's no so convenient way for this application, but just for trying to understand the problem) , but it didn't work as well.
Tigran
A: 

Ok, here we come :) I resolve the problem, in not very nice way, but it seems that works correctly. As I mentioned above I used LoadContent method and it returns me the ListView object, but by the way it wasn't the ListView that UI actually uses. So to resolve that problem I add static property to hold my REAL ListView object (static as I have single DataTemplate that contains ListView shared across multiple TabItems, so the ListView shared too) and add event handler to my DataTemplate -> Loaded. Catching this event, that in my case raises only ones in lifetime of application, in RoutedEvent's OriginalSource I got the REAL ListView object that WPF engine uses for rendering on UI. Hope my solution will help someone. Thank you all.

Tigran
A: 

simply, if you have data grid, and template column, which contains data template,... you can use the following code sample,

TextBlock tBlock= (TextBlok)photoPathColumn.CellEditingTemplate.FindName("photo",photoPathColumn.GetCellContent(CustomersDataGrid.CurrentItem))

--where photo is the name of text block --where photoPathColumn is datagrid template column

Mohamed Abdo