Paul Michaels
Paul Michaels

Reputation: 16695

XAML controls not recognised in code-behind

I have a strange problem where a XAML control is not visible in the code behind. Here is a sample of the XAML:

<ListView Name="lvtest" Grid.Row="2" Grid.ColumnSpan="2" Margin="0,20,0,0" 
              ItemsSource="{Binding Content}" >
    <ListView.ItemTemplate>
        <DataTemplate>     
            <StackPanel>                                
                <WebView Name="contentView" Style="{StaticResource BodyTextStyle}" />
                <TextBlock Name="testtxt" Text="{Binding}" Style="{StaticResource BodyTextStyle}" Foreground="GreenYellow"/>

In the code behind:

this.lvtest is recognised, but:

this.contentView and this.testtxt are both not.

I've also tried x:Name.

I'm clearly missing something obvious here, I just can't see what.

EDIT:

To clarify, the textbox control was going to be used to display some formatted text based on the binding, but what I have discovered is that the text is HTML formatted (this suggests using a WebView control). As far as I can see I need to NavigateToString to use the WebView control, and so can't bind it as such.

Upvotes: 3

Views: 6894

Answers (2)

Tim S.
Tim S.

Reputation: 56536

What you're missing is that the elements defined in a DataTemplate may be on the page any number of times, which can even change while running. Which one should be linked to the contentView field? There's no good way to answer that, so it simply doesn't create a contentView field.

To put it another way, you're not defining that the page includes those elements, you're declaring a template from which .NET can create elements.

If you let us know how you're trying to use it, we might be able to suggest another way.

Edit: Something like this might work for you:

<WebView Loaded="contentView_Loaded" Style="{StaticResource BodyTextStyle}" />

Then in the code:

void contentView_Loaded(object sender, EventArgs e)
{
    var contentView = (WebView)sender;
    var dataContext = (YourDataType)contentView.DataContext;
    // do something
}

Upvotes: 8

Chris Gessler
Chris Gessler

Reputation: 23113

They are hidden because they are inside a template control.

From http://social.msdn.microsoft.com/Forums/en/wpf/thread/29ecc8ee-26ee-4331-8f97-35ff9d3e6886

<ListView  Name="listview">

    <ListView.ItemTemplate>

        <DataTemplate>

            <StackPanel Orientation="Horizontal" >

            <TextBlock Name="textYear" Text="{Binding Year}" />

                <TextBlock  Text="  " />

             <TextBlock Name="textDayOffWeek" Text="{Binding DayOfWeek}" />

                </StackPanel>

        </DataTemplate>

    </ListView.ItemTemplate>

    <s:DateTime >1/2/2007</s:DateTime>

    <s:DateTime >1/3/2008</s:DateTime>

    <s:DateTime >1/5/2007</s:DateTime>

    <s:DateTime >1/6/2006</s:DateTime>

</ListView>

    <Button Width="180" Height="30" Content="Find TextBlock in DataTemplate" Click="FindElement" />

    </StackPanel>

In the code behind:

  private void FindElement(object sender, RoutedEventArgs e)

    {

        // get the current selected item

        ListViewItem item = listview.ItemContainerGenerator.ContainerFromIndex(listview.SelectedIndex) as ListViewItem;

        TextBlock textYear = null;

        if (item != null)

        {

            //get the item's template parent

            ContentPresenter templateParent = GetFrameworkElementByName<ContentPresenter>(item);

            //get the DataTemplate that TextBlock in.

            DataTemplate dataTemplate = listview.ItemTemplate;

            if (dataTemplate != null && templateParent != null)

            {

                 textYear = dataTemplate.FindName("textYear", templateParent) as TextBlock;

            }

            if (textYear != null)

            {

                MessageBox.Show(String.Format("Current item's Year is:{0}", textYear.Text));

            }

        }



    }

    private static T GetFrameworkElementByName<T>(FrameworkElement referenceElement) where T : FrameworkElement

    {

        FrameworkElement child = null;

        for (Int32 i = 0; i < VisualTreeHelper.GetChildrenCount(referenceElement); i++)

        {

            child = VisualTreeHelper.GetChild(referenceElement, i) as FrameworkElement;

            System.Diagnostics.Debug.WriteLine(child);

            if (child != null && child.GetType() == typeof(T))

            { break; }

            else if (child != null)

            {

                child = GetFrameworkElementByName<T>(child);

                if (child != null && child.GetType() == typeof(T))

                {

                    break;

                }

            }

        }

        return child as T;

    }

Upvotes: 3

Related Questions