正當我認爲自己在這方面越來越好時,TabControl現在給我帶來了問題。我已經在StackOverflow上閱讀過相關文章,但一直無法讓我的簡單演示應用程序按照我希望的方式工作。在WPF中使用TabControl和MVVM進行正確的數據綁定
爲了保持專注,我將從一個關於我不明白的問題開始。
我有一個TabControl的TabItems每個託管相同的UserControl。當我將TabControl.ContentTemplate的DataTemplate設置爲我的UserControl時,將出現該控件的呈現,但它看起來像是每個選項卡的相同控件。或者,也許它並不依賴於任何標籤。
MainWindow.xaml
<Window x:Class="TabControlMvvm.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:localviews="clr-namespace:TabControlMvvm.Views"
Title="MainWindow" Height="350" Width="525">
<TabControl ItemsSource="{Binding Tabs}" SelectedIndex="{Binding Selected}">
<TabControl.ContentTemplate>
<DataTemplate>
<localviews:PersonMainPanel />
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
</Window>
代碼隱藏僅設置視圖模型作爲其的DataContext:
namespace TabControlMvvm {
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window {
public MainWindow()
{
InitializeComponent();
DataContext = new TabControlMvvm.ViewModels.MainViewModel();
}
}
}
的TabItem的的內容應該是另一個用戶控件,PersonMainPanel.xaml:
<UserControl x:Class="TabControlMvvm.Views.PersonMainPanel"
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:localviews="clr-namespace:TabControlMvvm.Views"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Border BorderBrush="Red" BorderThickness="2">
<TabControl TabStripPlacement="Bottom">
<TabItem Header="Tab 1">
<localviews:MyTabItem />
</TabItem>
<TabItem Header="Tab 2">
<TextBlock Text="This was left blank intentionally" />
</TabItem>
<TabItem Header="Tab 3">
<TextBlock Text="This was also left blank intentionally" />
</TabItem>
</TabControl>
</Border>
</UserControl>
代碼隱藏:
namespace TabControlMvvm.Views {
/// <summary>
/// Interaction logic for PersonMainPanel.xaml
/// </summary>
public partial class PersonMainPanel : UserControl {
public PersonMainPanel()
{
InitializeComponent();
}
}
}
而且MainViewModel:
namespace TabControlMvvm.ViewModels {
public class MainViewModel : ViewModelBase {
public ICollectionView Tabs { get; set; }
public int Selected { get; set; }
public class Person
{
public string Name { get; set; }
}
public class DummyController {
public List<Person> Persons { get; private set; }
public DummyController()
{
Persons = new List<Person> {
new Person { Name = "Larry" },
new Person { Name = "Darryl" },
new Person { Name = "Other brother Darryl" }
};
}
}
public DummyController Controller { get; private set; }
public RelayCommand HelloCommand { get; set; }
public MainViewModel()
{
Controller = new DummyController();
/*
IEnumerable<TabItem> tabs = Enumerable.Range(1, _controller.Persons.Count())
.Select(x => new TabItem { Header = String.Format("Person {0}", x),
Content = new PersonMainPanel() });
*/
IEnumerable<TabItem> tabs = Enumerable.Range(1, Controller.Persons.Count())
.Select(x => new TabItem { Header = String.Format("Person {0}", x)});
Tabs = CollectionViewSource.GetDefaultView(tabs.ToList());
Tabs.MoveCurrentToFirst();
InitializeCommands();
}
private void InitializeCommands()
{
HelloCommand = new RelayCommand(() => { MessageBox.Show(String.Format("Hello, Person {0} named {1}!",
Selected, Controller.Persons[Selected].Name)); });
}
}
}
PersonMainPanel舉辦另一TabControl的,在標籤1的內容是MyTabItem.xaml:
<UserControl x:Class="TabControlMvvm.Views.MyTabItem"
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"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Name:" />
<TextBox Text="{Binding Name}" Width="100" />
</StackPanel>
<Button Command="{Binding HelloCommand}" Content="Say Hello" />
</StackPanel>
</UserControl>
代碼隱藏:
namespace TabControlMvvm.Views {
/// <summary>
/// Interaction logic for MyTabItem.xaml
/// </summary>
public partial class MyTabItem : UserControl {
public MyTabItem()
{
InitializeComponent();
}
}
}
它看起來像這樣在運行時間:
問題我至今:
- 當我輸入第1個人的名稱,然後單擊此人2片,1個人的名稱仍是可見的,因此我假設控件沒有正確數據綁定。我明白ItemsControls不會將他們的DataContext傳遞給他們的孩子,但我不知道如何解決這個問題,而不需要在代碼隱藏中關聯View。
- 由於缺少DataContext,我會期望在Output窗口中獲得數據綁定錯誤,但我沒有收到任何錯誤。我假設DataContext爲null,但是這不會導致綁定錯誤嗎?
- 如何有效地使用Snoop來調試這樣的問題?
這裏的樣品溶液:http://www.filedropper.com/tabcontrolmvvm
也許有所幫助:https://stackoverflow.com/a/1870658/1136211 – Clemens
如何你MainViewModel看? – sTrenat
哎呀,忘了明顯!編輯。另外,@Clemens從你的鏈接文章中獲取的一點是,後備集合不應該是TabItems,它應該可能是MyTabItem的ViewModel。指定DataTemplate的XAML應該保持原樣。我現在會嘗試,以防萬一這是我的問題! – Dave