간단한 데이터 바인딩 문제가있는 것 같지만 올바른 방법은 없습니다. 두 개의 DataTemplate
을 정의하는 TabControl
이 있습니다. 하나는 탭 헤더 용이고 다른 하나는 탭 내용 용입니다.DataTemplate에서 ItemsControl을 바인딩하는 데이터
콘텐츠 템플릿에 ItemsControl
이 포함되어 있습니다. ItemsControl은 동적으로 생성 된 ViewModel
(ConnectionInfoVM)에 바인딩을 시도합니다.
UI를 표시하면 바인딩이 실패하지만 출력에 오류 메시지가 표시되지 않습니다.
바인딩이 작동하고 DataBuffer가 실제로 표시되도록 DataContext와 바인딩을 설정해야하는 이유는 무엇입니까? 어떤 도움이라도 대단히 감사합니다.
ConnectionsControl :
<UserControl x:Class="XXXViewer.Views.ConnectionsControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:viewModels="clr-namespace:XXXViewer.ViewModels"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TabControl Grid.Row="0" Name="TabDynamic" SelectionChanged="tabDynamic_SelectionChanged">
<TabControl.Resources>
<DataTemplate x:Key="TabHeader" DataType="TabItem">
<DockPanel>
<TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type TabItem}}, Path=Header}" />
<Button Name="btnDelete" DockPanel.Dock="Right" Margin="5,0,0,0" Padding="0" Click="btnTabDelete_Click" CommandParameter="{Binding RelativeSource={RelativeSource AncestorType={x:Type TabItem}}, Path=Name}">
<Image Source="{DynamicResource DeleteImg}" Height="11" Width="11"></Image>
</Button>
</DockPanel>
</DataTemplate>
<DataTemplate x:Key="TabContent" DataType="viewModels:ConnectionInfoVM">
<StackPanel>
<ScrollViewer Name="Scroller" Background="Black">
<StackPanel>
<TextBlock Text="This line gets printed" Foreground="White" FontFamily="Consolas"/>
<ItemsControl Name="ItemCtrl" ItemsSource="{Binding DataBuffer}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=.}" Foreground="White" FontFamily="Consolas"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</ScrollViewer>
</StackPanel>
</DataTemplate>
</TabControl.Resources>
</TabControl>
</Grid>
</UserControl>
ConnectionsControl 코드 숨김
namespace XXXViewer.Views
{
public partial class ConnectionsControl : UserControl
{
private readonly ObservableCollection<TabItem> _tabItems = new ObservableCollection<TabItem>();
public ConnectionsControl()
{
InitializeComponent();
// bindings
TabDynamic.ItemsSource = _tabItems;
TabDynamic.DataContext = this;
}
// assume this gets called
private void AddTabItem(ConnectionInfoVM ci)
{
DataTemplate headerTemplate = TabDynamic.FindResource("TabHeader") as DataTemplate;
DataTemplate contentTemplate = TabDynamic.FindResource("TabContent") as DataTemplate;
// create new tab item
TabItem tab = new TabItem
{
Header = $"Tab {ci.ConnectionID}",
Name = $"T{ci.ConnectionID}",
HeaderTemplate = headerTemplate,
ContentTemplate = contentTemplate,
DataContext = ci
};
_tabItems.Insert(0, tab);
// set the new tab as active tab
TabDynamic.SelectedItem = tab;
}
}
}
ConnectionInfoVM : resulting tab
,536,913 : 작성되는 탭의namespace XXXViewer.ViewModels
{
public class ConnectionInfoVM : ViewModelBase
{
private readonly ObservableQueue<string> _dataBuffer = new ObservableQueue<string>();
public ObservableQueue<string> DataBuffer => _dataBuffer;
}
}
스크린 샷
제안 된 변경 사항과 함께 작동합니다. 따라서이 권리를 이해한다면 이것이 작동하는 방법입니다. 항목의 내용을 설정해야합니다. 내용에 따라 일치하는 템플리트가 선택됩니다. DataContext는 암시 적으로 내가 설정 한 컨텐트가 될 것입니다 (DataTemplate이 적용된 객체 임). 이 문제를 해결해 주셔서 감사합니다. – ptair
@ptair는 더 많은 정보와 더 많은 "WPF"접근법을 포함하도록 내 게시물을 편집했습니다. ItemsSource를 XAML에 바인딩하면 뒤에 컨트롤을 만들 필요가 없습니다. 실제로 DataTemplate에 키를 제공하지 않으면 ContentTemplate이 내용 유형에 따라 암시 적으로 선택됩니다. – nkoniishvt
@ptair 코드를 여러 번 수정하여 실수를 저 지르려고했습니다. 거의 작동해야합니다. – nkoniishvt