Pregunta

Estoy tratando de mostrar información sobre herramientas para un elemento generado por un ItemsControl que necesita extraer datos de fuentes conceptualmente no relacionadas. Por ejemplo, supongamos que tengo una clase de elemento de la siguiente manera:

public class Item
{
    public string ItemDescription { get; set; }
    public string ItemName { get; set; }
}

Puedo mostrar el elemento dentro de un control Items con una información sobre herramientas de la siguiente manera:

<ItemsControl x:Name="itemsControl" ItemsSource="{Binding Items}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding ItemName}">
                <TextBlock.ToolTip>
                    <ToolTip>
                        <TextBlock Text="{Binding ItemDescription}" />
                    </ToolTip>
                </TextBlock.ToolTip>
            </TextBlock>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

Pero supongamos que tengo otra propiedad a la que se puede acceder a través del DataContext del ItemsControl . ¿Hay alguna manera de hacer esto desde la información sobre herramientas? Por ejemplo,

<ItemsControl x:Name="itemsControl" ItemsSource="{Binding Items}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding ItemName}">
                <TextBlock.ToolTip>
                    <ToolTip>
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition />
                                <RowDefinition />
                            </Grid.RowDefinitions>
                            <TextBlock Text="{Binding ItemDescription}" />
                            <TextBlock Grid.Row="1" Text="{Bind this to another property of the ItemsControl DataContext}" />
                        </Grid>
                    </ToolTip>
                </TextBlock.ToolTip>
            </TextBlock>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

El código para la ventana de prueba que utilicé es el siguiente:

public partial class Window1 : Window
{
    public Window1()
    {
        InitializeComponent();

        List<Item> itemList = new List<Item>() {
            new Item() { ItemName = "First Item", ItemDescription = "This is the first item." },
            new Item() { ItemName = "Second Item", ItemDescription = "This is the second item." } 
        };

        this.Items = itemList;
        this.GlobalText = "Something else for the tooltip.";
        this.DataContext = this;
    }

    public string GlobalText { get; private set; }

    public List<Item> Items { get; private set; }
}

Entonces, en este ejemplo, quiero mostrar el valor de la propiedad GlobalText (en realidad, este sería otro objeto personalizado).

Para complicar las cosas, en realidad estoy usando DataTemplates y muestro dos tipos diferentes de objetos dentro de ItemsControl, ¡pero cualquier ayuda sería muy apreciada!

¿Fue útil?

Solución

Después de una hora de tirar del cabello, he llegado a la convicción de que no puede hacer referencia a otro DataContext dentro de un DataTemplate para obtener información sobre herramientas . Para otros enlaces es perfectamente posible, ya que otros carteles han demostrado. Es por eso que tampoco puedes usar el truco RelativeSource. Lo que puede hacer es implementar una propiedad estática en su clase de elemento y hacer referencia a que :

<Window x:Class="ToolTipSpike.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300"
    Name="Root"
    xmlns:ToolTipSpike="clr-namespace:ToolTipSpike">
    <Grid>
        <ItemsControl x:Name="itemsControl" ItemsSource="{Binding Items}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding ItemName}"> 
                        <TextBlock.ToolTip>
                            <ToolTip>
                                <Grid>
                                    <Grid.RowDefinitions>
                                        <RowDefinition />
                                        <RowDefinition />
                                    </Grid.RowDefinitions>
                                    <TextBlock Text="{Binding ItemDescription}" />
                                    <TextBlock Grid.Row="1" 
                   Text="{Binding Source={x:Static ToolTipSpike:Item.GlobalText},
                   Path=.}"
                                    />
                                </Grid>
                            </ToolTip>
                        </TextBlock.ToolTip>
                    </TextBlock>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </Grid>
</Window>

using System.Collections.Generic;
using System.Windows;

namespace ToolTipSpike
{
    public partial class Window1 : Window
    {

        public List<Item> Items { get; private set; }
        public Window1()
        {
            InitializeComponent();
            var itemList = new List<Item>
                  {
                      new Item { ItemName = "First Item", ItemDescription = "This is the first item." },
                      new Item { ItemName = "Second Item", ItemDescription = "This is the second item." }
                  };
            this.Items = itemList;
            this.DataContext = this;
       }
    }

     public class Item
     {
         static Item()
         {
             GlobalText = "Additional Text";
         }
         public static string GlobalText { get; set; }
         public string ItemName{ get; set;}
         public string ItemDescription{ get; set;}
     }
}

Otros consejos

Segundo intento

Ok, el enlace de origen relativo no funciona en este caso . Realmente funciona a partir de una plantilla de datos, puede encontrar muchos ejemplos de esto en Internet. Pero aquí (tenía razón, David, en su comentario) ToolTip es una bestia especial que no se coloca correctamente en el VisualTree (es una propiedad, no un control per se) y no tiene acceso al alcance del nombre adecuado para usar enlace relativo.

Después de buscar más, encontré este artículo , que describe este efecto en detalles y propone una implementación de BindableToolTip.

Puede ser una exageración, porque tiene otras opciones, como usar una propiedad estática en una clase (como en la respuesta de Dabblernl) o agregar una nueva propiedad de instancia a su Item .

Primer intento :)

Debe consultar con los tipos de enlace de fuente relativa (en esta hoja de trucos para ejemplo):

Entonces su encuadernación se verá de alguna manera similar a esto:

{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}}, Path= GlobalText}

Yacoder casi correcto, y adiviné muy mal allí Dabblernl;)

Su forma de pensar es correcta y es posible hacer referencia al DataContext de su ItemsControl

Falta la propiedad DataContext en la ruta:

{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}}, Path=DataContext.GlobalText}

Segundo intento;)

http: / /blogs.msdn.com/tom_mathews/archive/2006/11/06/binding-a-tooltip-in-xaml.aspx

Aquí hay un artículo con el mismo problema. Pueden hacer referencia al DataContext de su control primario mediante la propiedad PlacementTarget:

<ToolTip DataContext=”{Binding RelativeSource={RelativeSource Self},Path=PlacementTarget.Parent}”>

Si coloca el DataContext en un nivel más profundo, evite cambiar su Item DataContext

  

Una segunda sugerencia (Neil y Adam Smith) fue que podríamos usar PlacementTarget en el enlace. Esto es bueno, ya que en realidad ya estoy heredando el DataContext de la página que aloja el DataControl, y esto permitiría que la información sobre herramientas vuelva a tener acceso al control original. Sin embargo, como señaló Adam, debe tener en cuenta la estructura padre / hijo de su marcado:

Este es un caso en el que creo que es conceptualmente más apropiado hacer esto en el modelo de vista que en la vista de todos modos. Exponga la información de información sobre herramientas a la vista como una propiedad del elemento del modelo de vista. Eso permite que la vista haga lo que es bueno (presentar las propiedades del elemento) y que el modelo de vista haga lo que sea bueno (decidir qué información se debe presentar).

Tuve un problema muy similar y llegué a esta pregunta buscando respuestas. Al final se me ocurrió una solución diferente que funcionó en mi caso y puede ser útil para otros.

En mi solución, agregué una propiedad al elemento secundario que hace referencia al modelo principal y la completé cuando se generaron los elementos secundarios. En el XAML para la información sobre herramientas, simplemente hice referencia a la propiedad del modelo principal en cada elemento y configuré el DataContext a la propiedad del modelo principal.

Me sentí más cómodo con esta solución que crear elementos proxy en XAML y hacer referencia a ellos.

Usando el código de ejemplo para esta pregunta, haría lo siguiente. Tenga en cuenta que no he probado este escenario en un compilador, pero lo he implementado con éxito esta solución en el código para mi propio escenario.

Elemento:

public class Item
{
    public List<Item> Parent { get; set; }
    public string ItemDescription { get; set; }
    public string ItemName { get; set; }
}

Ventana:

public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();

            List<Item> itemList = new List<Item>();
            itemList.Add(new Item() { Parent = this, ItemName = "First Item", ItemDescription = "This is the first item." });
            itemList.Add(new Item() { Parent = this, ItemName = "Second Item", ItemDescription = "This is the second item." });


            this.Items = itemList;
            this.GlobalText = "Something else for the tooltip.";
            this.DataContext = this;
        }

        public string GlobalText { get; private set; }

        public List<Item> Items { get; private set; }
    }

XAML:

<ItemsControl x:Name="itemsControl" ItemsSource="{Binding Items}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding ItemName}">
                <TextBlock.ToolTip>
                    <ToolTip>
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition />
                                <RowDefinition />
                            </Grid.RowDefinitions>
                            <TextBlock Text="{Binding ItemDescription}" />
                            <TextBlock Grid.Row="1" DataContext={Binding Parent} Text="{Bind this to aproperty of the parent data model}" />
                        </Grid>
                    </ToolTip>
                </TextBlock.ToolTip>
            </TextBlock>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top