我正在使用 MVVM 从 viewModel 动态创建选项卡。在代码中,我的尝试是保存“TabItem”的集合,该集合指定选项卡的显示方式(自定义模板)以及 ModelView 对象,然后基于 TabItem 视图 #1 / 或视图 #2 上的模型视图显示。
我目前的软件架构如下:
我的 MainWindow.xaml:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ViewModel="clr-namespace:MyApp.ViewModel" x:Class="MyApp.MainWindow"
xmlns:Views="clr-namespace:MyApp.View"
Height="700" Width="1000" Background="#FF1B0000" ResizeMode="NoResize">
<Window.DataContext>
<ViewModel:TabItemViewModel/>
</Window.DataContext>
<Grid>
<TabControl Background="Black" Margin="0,25,0,0" BorderThickness="0,0,0,0" ItemsSource="{Binding Tabs}" BorderBrush="Black" >
<TabControl.ItemTemplate>
<!-- this is the header template-->
<DataTemplate>
<Grid Margin="0">
<Border Margin="0,0,0,0"
Background="Black"
BorderBrush="Black"
BorderThickness="0,0,0,0" Padding="0,0,0,0">
<StackPanel Orientation="Horizontal"
Margin="0,0,0,0">
<Image Name ="tabImage" Source="{Binding TabImage_Disabled}" />
</StackPanel>
</Border>
</Grid>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Path=IsSelected,RelativeSource={RelativeSource TemplatedParent}}" Value="True">
<Setter TargetName="tabImage" Property="Source" Value="{Binding TabImage_Enabled}"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<!-- this is the body of the TabItem template-->
<DataTemplate>
<TextBlock Text="{Binding TabContents}" Foreground="white" />
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
</Grid>
</Window>
TabItem.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Media.Imaging;
using MyApp.ViewModel;
namespace MyApp.Model
{
public sealed class TabItem
{
public string TabName { get; set; }
public BitmapImage TabImage_Enabled { get; set; }
public BitmapImage TabImage_Disabled { get; set; }
public BitmapImage TabImage_Background { get; set; }
public ViewModelBase TabContents { get; set; }
}
}
ViewModelBase.cs:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MyApp.ViewModel
{
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void RaisePropertyChanged(string propertyName)
{
var handler = this.PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
TabItemViewModel.cs:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Windows.Media.Imaging;
using MyApp.Model;
namespace MyApp.ViewModel
{
public sealed class TabItemViewModel : ViewModelBase
{
const int NUMBER_OF_TABS = 2;
enum enum_Tabs
{
Research_Tab = 0,
Engineering_Tab = 1
}
Uri[] _aUrisEnabled = new Uri[NUMBER_OF_TABS];
Uri[] _aUrisDisabled = new Uri[NUMBER_OF_TABS];
Uri[] _aUrisBackgroundPics = new Uri[NUMBER_OF_TABS];
BitmapImage[] _aEnabledTabImages = new BitmapImage[NUMBER_OF_TABS];
BitmapImage[] _aDisabledTabImages = new BitmapImage[NUMBER_OF_TABS];
BitmapImage[] _aBackgroundTabImages = new BitmapImage[NUMBER_OF_TABS];
private ObservableCollection<TabItem> _tabs;
public ObservableCollection<TabItem> Tabs
{
get { return _tabs; }
set
{
_tabs = value;
RaisePropertyChanged("Tabs");
}
}
public TabItemViewModel()
{
Tabs = new ObservableCollection<TabItem>();
// URIs
// enabled pics
_aUrisEnabled[(int)enum_Tabs.Research_Tab] = new Uri("pack://application:,,,/Images/research_enabled.png");
_aUrisEnabled[(int)enum_Tabs.Engineering_Tab] = new Uri("pack://application:,,,/Images/engineering_enabled.png");
// disabled pics
_aUrisDisabled[(int)enum_Tabs.Research_Tab] = new Uri("pack://application:,,,/Images/research_disabled.png");
_aUrisDisabled[(int)enum_Tabs.Engineering_Tab] = new Uri("pack://application:,,,/Images/engineering_disabled.png");
// Tab backgrounds
_aUrisBackgroundPics[(int)enum_Tabs.Research_Tab] = new Uri("pack://application:,,,/Images/research_background.png");
_aUrisBackgroundPics[(int)enum_Tabs.Engineering_Tab] = new Uri("pack://application:,,,/Images/engineering_background.png");
// Load all images
for (int iImageIndex = 0; iImageIndex < NUMBER_OF_TABS; iImageIndex++)
{
_aEnabledTabImages[iImageIndex] = new BitmapImage(_aUrisEnabled[iImageIndex]);
_aDisabledTabImages[iImageIndex] = new BitmapImage(_aUrisDisabled[iImageIndex]);
_aBackgroundTabImages[iImageIndex] = new BitmapImage(_aUrisBackgroundPics[iImageIndex]);
}
Tabs.Add(new TabItem { TabName = "Research", TabImage_Enabled = _aEnabledTabImages[(int)enum_Tabs.Research_Tab], TabImage_Disabled = _aDisabledTabImages[(int)enum_Tabs.Research_Tab], TabImage_Background = _aBackgroundTabImages[(int)enum_Tabs.Research_Tab], TabContents = new TabResearchViewModel() });
Tabs.Add(new TabItem { TabName = "Engineering", TabImage_Enabled = _aEnabledTabImages[(int)enum_Tabs.Engineering_Tab], TabImage_Disabled = _aDisabledTabImages[(int)enum_Tabs.Engineering_Tab], TabImage_Background = _aBackgroundTabImages[(int)enum_Tabs.Engineering_Tab], TabContents = new TabEngineeringViewModel() });
}
}
}
我的问题是除了视图之外,我如何指定自定义模板(对于 TabHeader,因为我显示的是图片而不是 TextBlock)。
我试过在谷歌和这个网站上搜索,但找不到使用自定义模板的解决方案。我找到了 TempleateSelector 的一些解决方案,但我不确定如何将它与 MVVM 结合使用。
我还尝试在 MainWINdow.xaml 中编写类似的内容:
<TabControl Background="Black" Margin="0,25,0,0" BorderThickness="0,0,0,0" ItemsSource="{Binding Tabs}" BorderBrush="Black" >
<TabControl.Resources>
<DataTemplate DataType="{x:Type ViewModel:TabResearchViewModel}">
<Views:TabResearchView />
</DataTemplate>
<DataTemplate DataType="{x:Type ViewModel:TabEngineeringViewModel}">
<Views:TabEngineeringView />
</DataTemplate>
</TabControl.Resources>
... (removed for clarity)
我想
<TextBlock Text="{Binding TabContents}" Foreground="white" />
</DataTemplate>
用将显示“视图”(页面)的东西替换,同时绑定到选项卡集合......
非常感谢您对此事的任何帮助。先谢谢了...