Pergunta

Eu estou tentando exibir uma dica de ferramenta para um item gerado por um ItemsControl que as necessidades para extrair dados a partir de fontes conceitualmente não relacionados. Por exemplo, digamos que eu tenho uma classe Item da seguinte forma:

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

I pode exibir o item dentro de um ItemsControl com uma dica de ferramenta como segue:

<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>

Mas digamos que eu tenho uma outra propriedade que pode ser acessado através do DataContext do ItemsControl. Existe alguma maneira de fazer isso de dentro da dica? Por exemplo.,

<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>

O código para o teste Janela I utilizado é a seguinte:

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; }
}

Assim, neste exemplo eu quero mostrar o valor da propriedade GlobalText (na realidade, isso seria um outro objeto personalizado).

Para assuntos complicar, estou realmente usando DataTemplates e mostrar dois tipos diferentes de objetos dentro do ItemsControl, mas qualquer ajuda seria muito apreciada!

Foi útil?

Solução

Depois de uma hora de puxar cabelo Eu vim para a convicção de que você não pode fazer referência a outro DataContext dentro de um DataTemplate para uma dica de ferramenta . Para outras ligações é perfeitamente possível, como outros cartazes têm provado. É por isso que você não pode usar o truque RelativeSource quer. O que você pode fazer é implementar uma propriedade estática em sua classe Item e referência 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;}
     }
}

Outras dicas

segunda tentativa

Ok, a Fonte Relativa ligação não trabalho , neste caso, . Ele realmente funciona a partir de um modelo de dados, você pode encontrar muitos exemplos disso nos Internet. Mas aqui (você estava certo, David, em seu comentário) dica de ferramenta é uma besta especial que não está colocada corretamente na VisualTree (é uma propriedade, não um controle de per se) e que não tem acesso ao escopo nome próprio para usar relativa vinculativo.

Depois de algum mais procura achei este artigo , que descreve este efeito em detalhes e propõe uma implementação de um BindableToolTip.

Pode ser um exagero, porque você tem outras opções -. Como o uso de uma propriedade estática em uma classe (como na resposta de Dabblernl) ou adicionar uma nova propriedade de instância para o seu Item

Primeira tentativa:)

Você deve consultar com a Fonte Relativa tipos de ligação (em este folha de fraude para exemplo):

Assim sua ligação irá procurar de alguma forma semelhante a esta:

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

Yacoder Quase correto, e maneira errada adivinhou há Dabblernl;)

A sua maneira de pensar está correta e é possível referenciar o DataContext do seu ItemsControl

Está faltando a propriedade DataContext no caminho:

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

segunda tentativa;)

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

Aqui está um artigo com o mesmo problema. Eles podem referenciar o DataContext de sua controle pai pela propriedade PlacementTarget:

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

Se você colocaria o DataContext em um nível mais profundo, você evita mudar seu item DataContext

A segunda sugestão (Neil e Adam Smith) foi que poderíamos usar PlacementTarget na ligação. Isso é bom, como eu estou realmente herdar o DataContext já a partir da página que hospeda o DataControl, e isso permitiria que a dica de ferramenta para ter acesso de volta ao controle origial. Como Adam notou, porém, você tem que estar ciente da estrutura pai / filho fora de sua marcação:

Este é um caso em que eu acho que é conceitualmente mais apropriada para fazer isso no modelo de vista do que é na visualização de qualquer maneira. Expor as informações dica para a vista como uma propriedade do item de vista do modelo. Que permite a visualização fazer o que é bom em (apresentando propriedades do item) e o modelo de vista fazer o que é bom em (decidir que informação deve ser apresentada).

Eu tive um problema muito semelhante e chegou a esta pergunta em busca de respostas. No final, eu vim com uma solução diferente, que trabalhou no meu caso e pode ser útil para os outros.

Na minha solução, eu adicionei uma propriedade para o item filho que faz referência ao modelo pai, e preenchida quando as crianças foram gerados. No XAML para a dica de ferramenta, então eu simplesmente referenciada a propriedade do modelo pai em cada elemento e definir o DataContext para a propriedade modelo de pai.

Eu me senti mais confortável com esta solução de criar elementos de proxy no XAML e referenciá-los.

Usando o código de exemplo para esta pergunta, você faria o seguinte. Nota eu não testei este cenário em um compilador, mas o fizeram com sucesso implementado esta solução no código para o meu próprio cenário.

Item:

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

Janela:

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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top