7

ItemsControl概念的に無関係なソースからデータを取得する必要がある によって生成されたアイテムのツールチップを表示しようとしています。たとえば、次のような Item クラスがあるとします。

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

次のように、ツールチップを使用して ItemsControl 内にアイテムを表示できます。

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

DataContextしかし、の経由でアクセスできる別のプロパティがあるとしますItemsControl。ツールチップ内からこれを行う方法はありますか? 例えば、

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

私が使用したテスト ウィンドウのコードは次のとおりです。

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

したがって、この例では、プロパティの値を表示したいと思いGlobalTextます (実際には、これは別のカスタム オブジェクトになります)。

問題を複雑にするために、私は実際に DataTemplates を使用して、ItemsControl 内に 2 つの異なるタイプのオブジェクトを表示していますが、どんな支援も大歓迎です!

4

5 に答える 5

3

1時間の髪の毛の引っ張りの後、 ToolTip の DataTemplate 内で別の DataContext を参照できないという確信に至りました。他のバインディングについては、他のポスターが証明しているように完全に可能です。そのため、RelativeSource トリックも使用できません。できることは、Item クラスに静的プロパティを実装し、それを参照することです。

<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;}
     }
}
于 2009-12-01T13:23:59.360 に答える
1

これは、とにかくビューよりもビューモデルでこれを行う方が概念的に適切だと思う場合です。ツールチップ情報をビューモデルアイテムのプロパティとしてビューに公開します。これにより、ビューは得意なこと(アイテムのプロパティの表示)を実行し、ビューモデルは得意なこと(表示する情報の決定)を実行できます。

于 2010-02-06T19:08:51.300 に答える
1

2 回目の試行

この場合、相対ソース バインディングは機能しません。これは実際にはデータ テンプレートから機能します。インターネット上でこの例を多数見つけることができます。しかし、ここでは (デビッド、あなたのコメントであなたは正しかった) ToolTip は、VisualTree に正しく配置されていない特別な獣であり (それ自体はコントロールではなくプロパティです)、適切な名前のスコープにアクセスできません。相対バインディングを使用します。

さらに検索した後、この記事を見つけました。この記事では、この効果について詳しく説明し、BindableToolTip の実装を提案しています。

クラスで静的プロパティを使用したり(Dabblernlの応答のように)、新しいインスタンスプロパティをItem.

最初の試み :)

Relative Source Binding の種類を参照する必要があります (たとえば、このチート シートを参照)。

したがって、バインディングは次のようになります。

{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}}, Path= GlobalText}
于 2009-12-01T12:19:56.350 に答える
1

Yacoder はほぼ正しいですが、Dabblernl ではかなり間違っていると推測されます ;)

あなたの考え方は正しく、ItemsControl の DataContext を参照することは可能です。

パスに DataContext プロパティがありません:

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

二度目の試み;)

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

同じ問題の記事はこちらです。PlacementTarget プロパティによって親コントロールの DataContext を参照できます。

<ToolTip DataContext=”{Binding RelativeSource={RelativeSource Self},Path=PlacementTarget.Parent}”&gt;

DataContext をより深いレベルに配置する場合は、Item DataContext を変更しないでください。

2 番目の提案 (Neil と Adam Smith) は、バインディングで PlacementTarget を使用できるというものでした。DataControl をホストするページから既に DataContext を継承しているため、これは便利です。これにより、ToolTip が元のコントロールにアクセスできるようになります。ただし、Adam が指摘したように、マークアップの親子構造に注意する必要があります。

于 2009-12-01T13:48:01.060 に答える
1

私は非常によく似た問題を抱えていて、答えを求めてこの質問にたどり着きました。最終的に、私の場合はうまくいき、他の人にも役立つかもしれない別の解決策を思いつきました。

私のソリューションでは、親モデルを参照する子項目にプロパティを追加し、子が生成されたときにそれを設定しました。次に、ToolTip の XAML で、各要素の親モデルからプロパティを参照し、DataContext を親モデル プロパティに設定するだけです。

XAML でプロキシ要素を作成して参照するよりも、このソリューションの方が快適だと感じました。

この質問のコード例を使用すると、次のようになります。注: このシナリオをコンパイラでテストしたことはありませんが、このソリューションを自分のシナリオのコードに正常に実装しました。

アイテム:

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

窓:

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>
于 2013-06-28T03:58:04.093 に答える