Poser une questionPoser une question
 

TraitéeAcces to a button in a DataTemplate

  • samedi 28 octobre 2006 11:10Thomas LEBRUNMVPMédailles de l'utilisateurMédailles de l'utilisateurMédailles de l'utilisateurMédailles de l'utilisateurMédailles de l'utilisateur
     

    Hello everybody,

     

    In my application, I've got this XAML code:

    <Page.Resources>

    <SharepointListItemsViewer:NodeTemplateSelector x:Key="nodeTemplateSelector" />

    </Page.Resources>

     

    <Graph:Graph Name="theGraph" NodesBindingPath="ChildNodes"

    CoefficientOfDampening="0.7"

    FrameRate="0.5"

    NodeTemplateSelector="{StaticResource nodeTemplateSelector}">

    <Graph:Graph.Resources>

    <Style TargetType="{x:Type Button}">

    <Setter Property="Template">

    <Setter.Value>

    <ControlTemplate TargetType="{x:Type Button}">

    <Border Name="theBorder" BorderBrush="Gray" BorderThickness="2" CornerRadius="10" Padding="5" Background="{TemplateBinding Background}">

    <ContentPresenter/>

    </Border>

    <ControlTemplate.Triggers>

    <Trigger Property="IsMouseOver" Value="True">

    <Setter TargetName="theBorder" Property="BorderBrush" Value="#333333"/>

    </Trigger>

    <Trigger Property="IsPressed" Value="True">

    <Setter TargetName="theBorder" Property="Background" Value="#CCCCCC"/>

    </Trigger>

    </ControlTemplate.Triggers>

    </ControlTemplate>

    </Setter.Value>

    </Setter>

    </Style>

    <DataTemplate x:Key="nodeTemplate">

    <Button Background="BurlyWood" CommandParameter="{Binding }" Click="DisplayDetails" Name="btnodeTemplate">

    <StackPanel Orientation="Vertical">

    <Image Source="{Binding Path=Item.ImageUrl, Mode=OneWay, Converter={StaticResource ImageConverter}}" Name="ItemDisplayedImage" Width="50" Height="50" HorizontalAlignment="Center" />

    <TextBlock Text="{Binding Path=Item.Name}" FontSize="11" HorizontalAlignment="Center" />

    </StackPanel>

    </Button>

    </DataTemplate>

    <DataTemplate x:Key="PersonTemplate">

    <Button Background="BurlyWood" CommandParameter="{Binding }" Click="DisplayDetails" Name="btPersonTemplate">

    <Grid>

    <Grid.ColumnDefinitions>

    <ColumnDefinition />

    <ColumnDefinition />

    </Grid.ColumnDefinitions>

    <Grid.RowDefinitions>

    <RowDefinition Height="0.1*" />

    <RowDefinition Height="0.9*" />

    </Grid.RowDefinitions>

    <Image Source="{Binding Path=Item.ImageUrl, Mode=OneWay, Converter={StaticResource ImageConverter}}" Name="ItemDisplayedImage" Width="50" Height="50" HorizontalAlignment="Center" Grid.Row="0" Grid.ColumnSpan="2" />

    <WindowsFormsHost Name="HostPresenceControl" Grid.Row="1" Grid.Column="0" Margin="0,0,5,0">

    <Presence:Persona Name="UserPresence" />

    </WindowsFormsHost>

    <TextBlock Text="{Binding Path=Item.Name}" Grid.Row="1" Grid.Column="1" FontSize="11" HorizontalAlignment="Center" />

    </Grid>

    </Button>

    </DataTemplate>

    </Graph:Graph.Resources>

    </Graph:Graph>

    And here is the DataTemplateSelector class associated to this XAML code:

    internal class NodeTemplateSelector : DataTemplateSelector

    {

    public override DataTemplate SelectTemplate(object item, DependencyObject container)

    {

    Node<Item> node = item as Node<Item>;

    if (node != null)

    {

    // Select the correct NodeTemplate according to the type of the item

    if (node.Item.Type == ItemType.Person)

    {

    DataTemplate Template = ((FrameworkElement)container).FindResource("PersonTemplate") as DataTemplate;

    Button btn = Template.FindName("btPersonTemplate", ???) as Button;

    return (DataTemplate)((FrameworkElement)container).FindResource("PersonTemplate");

    }

    else

    {

    return (DataTemplate)((FrameworkElement)container).FindResource("nodeTemplate");

    }

    }

    return null;

    }

    }

    I want to ba able to access to the Button which is in my DataTemplate to do some binding on the WindowsFormsHost's Child (accessible using VisualTreeHelper class).

    But I don't know what I need to use here as a second parameter of the FindName mehod:

    Button btn = Template.FindName("btPersonTemplate", ???) as Button;

     

    Anyone have an idea ? Or maybe another/better idea ?

     

     

    Thanks !

     

    Thomas

Réponses

  • samedi 28 octobre 2006 14:15Thomas LEBRUNMVPMédailles de l'utilisateurMédailles de l'utilisateurMédailles de l'utilisateurMédailles de l'utilisateurMédailles de l'utilisateur
     Traitée

    OK, I've solved my problem using the LoadContent method of the DataTemplate:

     

    DataTemplate Template = ((FrameworkElement)container).FindResource("PersonTemplate") as DataTemplate;

    Button btn = Template.LoadContent() as Button;

    Grid grid = btn.Content as Grid;

    WindowsFormsHost host = grid.Children[1] as WindowsFormsHost;

    Persona UserPresence = host.Child as Persona;

    UserPresence.SipUri = node.Item.Email.ToLower();

     

     

    HTH

     

    Bye

Toutes les réponses

  • samedi 28 octobre 2006 12:05Zhou Yong Médailles de l'utilisateurMédailles de l'utilisateurMédailles de l'utilisateurMédailles de l'utilisateurMédailles de l'utilisateur
     
    Well, FindName method expects a valid parent which the template is applied, the tricky part is that there is no MSDN documentation on who's the valid templated parent for data template, actually the valid templated parent for DataTemplate is ContentPresenter, so in your original xaml, you should first grab a  reference to the  ContentPresenter inside the control template, then pass that reference to the Template.FindName() method as the second parameter.

    Sheva
  • samedi 28 octobre 2006 12:22Thomas LEBRUNMVPMédailles de l'utilisateurMédailles de l'utilisateurMédailles de l'utilisateurMédailles de l'utilisateurMédailles de l'utilisateur
     

    I've tri te following but I'm still having an error on the FindName method:

     

    Graph graph = (Graph)VisualTreeHelper.GetParent(((FrameworkElement)container));

    DataTemplate Template = graph.Resources["PersonTemplate"] as DataTemplate;

    Button btn = Template.FindName("btPersonTemplate", graph) as Button;

     

     

    :(

  • samedi 28 octobre 2006 12:51Thomas LEBRUNMVPMédailles de l'utilisateurMédailles de l'utilisateurMédailles de l'utilisateurMédailles de l'utilisateurMédailles de l'utilisateur
     

     Zhou Yong wrote:
    Well, FindName method expects a valid parent which the template is applied, the tricky part is that there is no MSDN documentation on who's the valid templated parent for data template, actually the valid templated parent for DataTemplate is ContentPresenter, so in your original xaml, you should first grab a  reference to the  ContentPresenter inside the control template, then pass that reference to the Template.FindName() method as the second parameter.

    Sheva

     

    Based on your idea, I've triied the following:

    Graph graph = (Graph)VisualTreeHelper.GetParent(((FrameworkElement)container));

    Graph.GraphContentPresenter contentPresenter = (Graph.GraphContentPresenter)VisualTreeHelper.GetChild(graph, 0);

    DataTemplate Template = graph.Resources["PersonTemplate"] as DataTemplate;

    Button btn = Template.FindName("btPersonTemplate", contentPresenter) as Button;

    But still with the error:

    This operation is valid only on elements that have this template applied.

    Any ideas ?

     

    Thanks !

     

     

    Thomas

  • samedi 28 octobre 2006 14:15Thomas LEBRUNMVPMédailles de l'utilisateurMédailles de l'utilisateurMédailles de l'utilisateurMédailles de l'utilisateurMédailles de l'utilisateur
     Traitée

    OK, I've solved my problem using the LoadContent method of the DataTemplate:

     

    DataTemplate Template = ((FrameworkElement)container).FindResource("PersonTemplate") as DataTemplate;

    Button btn = Template.LoadContent() as Button;

    Grid grid = btn.Content as Grid;

    WindowsFormsHost host = grid.Children[1] as WindowsFormsHost;

    Persona UserPresence = host.Child as Persona;

    UserPresence.SipUri = node.Item.Email.ToLower();

     

     

    HTH

     

    Bye

  • samedi 28 octobre 2006 14:16Zhou Yong Médailles de l'utilisateurMédailles de l'utilisateurMédailles de l'utilisateurMédailles de l'utilisateurMédailles de l'utilisateur
     
    Are you sure the contentPresenter you return is of ContentPresenter or is of ContentPresenter derivatives? or are you sure it's not  null?

    Sheva
  • samedi 28 octobre 2006 15:01Thomas LEBRUNMVPMédailles de l'utilisateurMédailles de l'utilisateurMédailles de l'utilisateurMédailles de l'utilisateurMédailles de l'utilisateur
     
    Yes, the GraphContentPresenter class inherit from ContentPresenter.