wpf itembertrol의 툴팁에서 여러 데이터 콘 테트의 데이터 표시
-
22-07-2019 - |
문제
나는 ItemsControl
개념적으로 관련이없는 출처에서 데이터를 가져와야합니다. 예를 들어, 다음과 같이 항목 클래스가 있다고 가정합니다.
public class Item
{
public string ItemDescription { get; set; }
public string ItemName { get; set; }
}
다음과 같이 툴팁을 사용하여 항목 통제 내에 항목을 표시 할 수 있습니다.
<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 내에 두 가지 다른 유형의 객체를 표시하지만 모든 도움은 크게 감사하겠습니다!
해결책
한 시간의 머리카락을 당기고 난 후에 나는 당신이 데이터 emplate 내부에서 다른 데이터 콘텍스트를 참조 할 수 없다는 확신을 얻었습니다. 툴팁의 경우. 다른 바인딩의 경우 다른 포스터가 입증 된 것처럼 완벽하게 가능합니다. 그렇기 때문에 친척 소스 트릭을 사용할 수 없습니다. 당신이 할 수있는 것은 항목 클래스 및 참조에서 정적 속성을 구현하는 것입니다. 저것:
<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;}
}
}
다른 팁
두 번째 시도
좋아, 상대 소스 바인딩은 작동하지 않습니다 이 경우. 실제로 데이터 템플릿에서 작동하며 인터넷에서 이에 대한 많은 예를 찾을 수 있습니다. 그러나 여기 (당신은 옳았습니다, David, 당신의 의견에서) 툴팁은 visualtree에 올바르게 배치되지 않는 특별한 짐승입니다 (그것은 제어 자체가 아닌 속성입니다). 상대 바인딩을 사용하십시오.
좀 더 검색 한 후 나는 찾았다 이 기사, 이 효과를 세부 사항으로 설명하고 BindableToolTip의 구현을 제안합니다.
클래스에서 정적 속성을 사용하거나 (Dabblernl의 응답에서와 같이) 다른 옵션이 있기 때문에 과잉 일 수 있습니다. Item
.
첫번째 시도 :)
상대 소스 바인딩 유형과 상담해야합니다 ( 이 치트 시트 예를 들어):
따라서 바인딩은 어떻게 든 이것과 유사하게 보일 것입니다.
{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}}, Path= GlobalText}
거의 올바른 Yacoder와 Dabblernl;)
귀하의 사고 방식은 정확하며 Itemscontrol의 데이터 콘텍스트를 참조 할 수 있습니다.
경로에서 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 속성으로 부모 컨트롤의 데이터 콘텍스트를 참조 할 수 있습니다.
<ToolTip DataContext=”{Binding RelativeSource={RelativeSource Self},Path=PlacementTarget.Parent}”>
DataContext를 더 깊은 수준으로 배치하는 경우 항목 Datacontext 변경을 피하십시오.
두 번째 제안 (Neil과 Adam Smith)은 우리가 바인딩에 배치를 사용할 수 있다는 것입니다. 실제로 데이터 콘트 롤을 호스팅하는 페이지에서 이미 데이터 컨텍스트를 상속하고 있기 때문에 이것은 좋습니다.이를 통해 툴팁이 오리지널 컨트롤에 다시 액세스 할 수 있습니다. 그러나 Adam이 지적했듯이, 당신은 당신의 마크 업에서 부모/자식 구조를 알고 있어야합니다.
이것은 어쨌든보기보다보기 모델에서 이것을하는 것이 개념적으로 더 적합하다고 생각하는 경우입니다. 도구 팁 정보를보기 모델 항목의 속성으로보기에 노출하십시오. 이는보기가 (항목의 속성을 제시)에서 잘하는 것을 수행 할 수있게하고보기 모델은 (어떤 정보를 제시 해야하는지 결정)에서 잘하는 것을 수행합니다.
나는 매우 비슷한 문제가 있었고이 질문에 답하기 위해 도달했습니다. 결국 나는 내 경우에 효과가 있었고 다른 사람들에게 유용 할 수있는 다른 솔루션을 생각해 냈습니다.
내 솔루션에서 나는 부모 모델을 참조하는 어린이 항목에 속성을 추가하고 어린이가 생성 될 때 채워졌습니다. 툴팁의 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>