从 DataTemplate 中绑定到 TabItem 标头
Posted
技术标签:
【中文标题】从 DataTemplate 中绑定到 TabItem 标头【英文标题】:Binding to a TabItem Header from within DataTemplate 【发布时间】:2021-08-22 14:41:48 【问题描述】:我正在尝试将 TabItem
内的 TextBox
的文本绑定到该 TabItem
的标题,以便标题和 TextBox 具有相同的内容(当标题为“测试" TextBox 也应该显示 "test")。
TextBox
是DataTemplate
的一部分,我将其用作StaticResource
的ContentTemplate
。 DataTemplate
工作正常,选项卡内的所有内容都按预期显示。只有TextBox
是空的。我尝试了很多方法来定义RelativeSource
,但到目前为止都没有奏效。
<DataTemplate x:Key="myTemplate">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Source="..."/>
<Border BorderBrush="Black" BorderThickness="0 0 0.2 0"/>
<StackPanel Grid.Column="1">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Content="Name: "/>
<TextBox Grid.Column="1" Text="Binding DataContext.Header,
RelativeSource=RelativeSource FindAncestor, AncestorType=x:Type TabItem"/>
<Button Grid.Column="3" Content="Speichern"/>
</Grid>
</StackPanel>
</Grid>
</DataTemplate>
编辑: 然后我使用这样的模板:
<TabControl>
<TabItem ContentTemplate="StaticResource myTemplate" Header="Test"/>
<TabItem Header="Tab 2"/>
<TabItem Header="Tab 3"/>
</TabControl>
【问题讨论】:
您需要数据上下文的属性还是 TabItem 本身的属性?如果是后者,请更正Text ="Binding Header, RelativeSource=RelativeSource FindAncestor, AncestorType =x:Type TabItem"
。
明确地说,您希望在文本框中输入的文本显示在标题上还是反之亦然?在第一种情况下,将Header
属性绑定到文本框的Text
属性,作为单向绑定,更新触发器已更改。在第二种情况下,您的操作与上述完全相反。
@EldHasp 我也试过了,可惜没用
@Rufw91 我想要第二种情况。你能给我一个示例代码吗?我对 wpf 还是有点陌生
我查看了动态视觉树 - 你是对的。选项卡的标题和内容位于不同的分支中。不同的面板用于他们的收藏。标题的呈现和内容之间的所有共同点只是数据上下文。因此,最简单的解决方案是向 Data Context 添加一个属性,标题和 TextBox 都将绑定到该属性。
【参考方案1】:
@EldHasp Я отредактировал свой вопрос。 Я не совсем понимаю, как работать с DataContext。 Как добавить другое свойство для привязки?
通常为某些特定数据类型创建数据模板。 在 ContentControl(包括 TabItem)中,数据进入 Content 属性(通常来自 DataContext 属性),而 ContentTemplate 中的模板指定其呈现。
以下是具有一个字符串属性的数据类型示例。 该示例使用BaseInpc class。
using Simplified;
namespace TabItemHeaderBinding
public class TabItemContent : BaseInpc
private string _title;
public string Title get => _title; set =>Set(ref _title, value);
典型的 WPF 是 MVVM 模式的实现。
在这种情况下,您将在 TabControl 源中收到一组元素 <TabControl ItemsSource =" Binding CollectionProperty "...>
。
在这种情况下,TabControl 会自动为 DataContext 中的每个项目创建一个 TabItem,并且在 Content 中它会传递相应的集合项目。
并且必须相对于该元素指定元素模板、标题等中的绑定。
您没有 MVVM,所以我展示了一个简单的示例,对您的初始代码进行了最小的更改。
<Window x:Class="TabItemHeaderBinding.ThbWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:TabItemHeaderBinding"
mc:Ignorable="d"
Title="ThbWindow" Height="450" Width="800">
<FrameworkElement.Resources>
<DataTemplate x:Key="myTemplate" DataType="x:Type local:TabItemContent">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Source="/Febr20y;component/Image/block.png"/>
<Border BorderBrush="Black" BorderThickness="0 0 0.2 0"/>
<StackPanel Grid.Column="1">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Content="Name: "/>
<TextBox Grid.Column="1" Text="Binding Title, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged"/>
<Button Grid.Column="3" Content="Speichern"/>
</Grid>
</StackPanel>
</Grid>
</DataTemplate>
</FrameworkElement.Resources>
<Grid>
<TabControl>
<TabItem ContentTemplate="StaticResource myTemplate"
Header="Binding Title"
Content="Binding">
<TabItem.DataContext>
<local:TabItemContent Title="TitleTest"/>
</TabItem.DataContext>
</TabItem>
<TabItem Header="Tab 2"/>
<TabItem Header="Tab 3"/>
</TabControl>
</Grid>
</Window>
Работает отлично
MVVM 实施示例:
namespace TabItemHeaderBinding
public class TabItemImageContent : TabItemContent
private object _imageSource;
public object ImageSource get => _imageSource; set =>Set(ref _imageSource, value);
using System.Collections.ObjectModel;
namespace TabItemHeaderBinding
public class TabItemContentViewModel
public ObservableCollection<TabItemImageContent> Tabs get;
= new ObservableCollection<TabItemImageContent>()
new TabItemImageContent() Title = "First", ImageSource="/Febr20y;component/Image/block.png",
new TabItemImageContent() Title = "Second", ImageSource="/Febr20y;component/Image/RAnimated1.gif",
new TabItemImageContent() Title = "Third", ImageSource="/Febr20y;component/Image/plus.jpg",
;
<Window x:Class="TabItemHeaderBinding.ThbMvvmWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:TabItemHeaderBinding"
mc:Ignorable="d"
Title="ThbMvvmWindow" Height="450" Width="800">
<FrameworkElement.Resources>
<DataTemplate x:Key="myTemplate" DataType="x:Type local:TabItemImageContent">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Source="Binding ImageSource"/>
<Border BorderBrush="Black" BorderThickness="0 0 0.2 0"/>
<StackPanel Grid.Column="1">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Content="Name: "/>
<TextBox Grid.Column="1" Text="Binding Title, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged"/>
<Button Grid.Column="3" Content="Speichern"/>
</Grid>
</StackPanel>
</Grid>
</DataTemplate>
</FrameworkElement.Resources>
<FrameworkElement.DataContext>
<local:TabItemContentViewModel/>
</FrameworkElement.DataContext>
<Grid>
<TabControl ItemsSource="Binding Tabs"
ContentTemplate="DynamicResource myTemplate">
<TabControl.ItemContainerStyle>
<Style TargetType="TabItem">
<Setter Property="Header" Value="Binding Title"/>
</Style>
</TabControl.ItemContainerStyle>
</TabControl>
</Grid>
</Window>
【讨论】:
我强烈推荐学习 MVVM。这样您就可以更轻松地实施许多解决方案。 我用一个示例 MVVM 实现补充了我的答案。你看看并研究它。对你很有帮助。 再次感谢,我会努力理解的:)以上是关于从 DataTemplate 中绑定到 TabItem 标头的主要内容,如果未能解决你的问题,请参考以下文章
ItemsControl 中 DataTemplate 中的 WPF UserControl - 如何绑定到 ItemsSource 的父级