我是一個新的WPF用戶,我試圖圍繞模板包裹頭部。特別是我試圖模板一個TabControl。WPF TabControl模板
我對TabControl綁定到數據時實際產生的控件感到困惑。我需要的是每個選項卡在其內容部分都有一個單獨的控件副本。我發現的是,似乎創建了一組控件,並且當用戶從標籤頁到標籤頁單擊時,只是綁定的數據發生更改。
項目描述:
示例項目包括與一個TabControl的單一視圖的。在TabControl的內容模板中是一個ListBox。視圖被綁定到TabBindingViewModel類的對象。這個類有一個名爲Tabs的屬性,它是TabViewModel對象的ObservableCollection。 TabViewModel類有兩個屬性:TabHeader和Guid。 TabViewModel.TabHeader是一個字符串,它包含將出現在選項卡上的文本,而TabViewModel.Guids是一個字符串的ObservableCollection。
當綁定,每個TabViewModel的TabBindingViewModel.Tabs集合中應該產生在與突片是所述TabViewModel.TabHeader屬性的報頭中的TabControl對象標籤。每個選項卡的內容應該是在TabViewModel.Guids集合中填充了字符串集合的ListBox。
問題
這一切都似乎呈現/綁定就好,但如果改變列表框的狀態(例如滾動或選擇項目),然後改變標籤,看來該狀態進行轉移到您剛剛選擇的新選項卡上的列表框。這使得我假設只有ListBox的一個實例(而不是5個單獨的實例),並且當您更改選項卡時,數據是唯一發生更改的事物。
在另一個場景中,我沒有將集合綁定到模板,而是使用它自己的xaml中的ListBox顯式定義每個TabItem對象。這一次,當我從標籤點擊標籤時,每個ListBox保持它自己的狀態。
我的假設是否正確?如果是這樣,我怎樣才能在第二種情況下實現結果,同時仍然利用模板? (這是一個簡化的例子,我的真實世界內容要複雜得多)
在此先感謝您的幫助!
我的例子的源代碼如下。
視圖類
1. TabBinding
<Window x:Class="TabBindingQuestion.View.TabBinding"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:TabBindingQuestion.ViewModel"
Title="TabTemplateView"
Height="344" Width="618">
<Window.Resources>
<vm:TabBindingViewModel x:Key="Data" />
</Window.Resources>
<Grid DataContext="{StaticResource Data}">
<TabControl Width="Auto"
Height="Auto"
ItemsSource="{Binding Tabs}"
IsSynchronizedWithCurrentItem="True">
<TabControl.ItemContainerStyle>
<Style TargetType="TabItem">
<Setter Property="Header" Value="{Binding TabHeader}" />
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<ListBox Width="Auto"
Height="Auto"
ItemsSource="{Binding Guids}" />
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</TabControl.ItemContainerStyle>
</TabControl>
</Grid>
</Window>
視圖模型類
2. ViewModelBase
using System.ComponentModel;
namespace TabBindingQuestion.ViewModel
{
class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(object sender, string propertyName)
{
if (this.PropertyChanged != null)
{
PropertyChanged(sender, new PropertyChangedEventArgs(propertyName));
}
}
}
}
3。TabBindingViewModel
using System.Collections.ObjectModel;
namespace TabBindingQuestion.ViewModel
{
class TabBindingViewModel : ViewModelBase
{
#region Members
private ObservableCollection<TabViewModel> _Tabs;
public ObservableCollection<TabViewModel> Tabs
{
get { return _Tabs; }
set
{
_Tabs = value;
OnPropertyChanged(this, "Tabs");
}
}
#endregion
#region Constructor
public TabBindingViewModel()
{
var tabs = new ObservableCollection<TabViewModel>();
for (int i = 1; i <= 5; i++)
{
tabs.Add(new TabViewModel() { TabHeader = "Tab " + i.ToString() });
}
Tabs = tabs;
}
#endregion
}
}
4. TabViewModel
using System;
using System.Collections.ObjectModel;
namespace TabBindingQuestion.ViewModel
{
class TabViewModel : ViewModelBase
{
#region Members
private string _TabHeader;
public string TabHeader
{
get { return _TabHeader; }
set
{
_TabHeader = value;
OnPropertyChanged(this, "TabHeader");
}
}
private ObservableCollection<string> _Guids;
public ObservableCollection<string> Guids
{
get { return _Guids; }
set
{
_Guids = value;
OnPropertyChanged(this, "Guids");
}
}
#endregion
#region Constructors
public TabViewModel()
{
var guids = new ObservableCollection<string>();
for (int i = 1; i < 100; i++)
{
guids.Add(Guid.NewGuid().ToString());
}
Guids = guids;
}
#endregion
}
}
謝謝您的回覆。 雖然你提出的建議不是一個可行的解決方案。由於每個選項卡的內容在實際場景中要複雜得多,並且包含複雜的第三方控件。此外,潛在的大量數據綁定到第三方控件,並且當用戶導航到不同的選項卡時,我無法保證重新綁定數據。 – BigFunger 2010-11-11 19:40:48
如果我明確地定義了5個標籤,每個標籤具有相同的內容(除了綁定到它們的數據),我就可以獲得我所追求的功能。但是,我希望功能根據我的收藏大小動態變化,而且我顯然不想複製該代碼。我發現很難相信沒有辦法使用模板來複制它。 – BigFunger 2010-11-11 19:46:03
Hrrm你可以嘗試在這裏找到的代碼:http://www.pluralsight-training.net/community/blogs/eburke/archive/2009/04/30/keeping-the-wpf-tab-control-from-destroying- its-children.aspx我使用它來防止TabControl在視圖不存在時銷燬它的子項,並且可能會應用相同的原則來維護每個選項卡的狀態。我現在沒有時間對它進行測試,但你可能能夠弄清楚它的一些事情 – Rachel 2010-11-11 21:10:11