通过WPF中的MVVM将不同的模型视图和视图绑定到每个TabItem

时间:2013-08-24 07:55:58

标签: wpf mvvm tabcontrol

我正在使用MVVM从viewModel动态创建标签。 在代码中,我的尝试是保存“TabItem”的集合,指定标签的显示方式(自定义模板)&另外还有ModelView对象,然后基于模型视图显示在TabItem视图#1 /或视图#2上。

我目前的s / w架构如下:

My 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() });
         }

     }
}

我的问题ID如何指定自定义模板(对于TabHeader,因为我显示图片而不是TextBlock)以及视图。

我尝试过搜索google&amp;在这个网站上,但找不到使用自定义模板的解决方案。 我找到了一些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> 用于显示“view”(页面)的内容,同时绑定到tabs集合...

感谢您对此事的任何帮助。 谢谢你提前......

1 个答案:

答案 0 :(得分:1)

没关系,我自己已经弄清楚了。

我的解决方案是: 1.将视图从Page替换为UserControl 2.用这一行替换“TextBlock”行:

<ContentPresenter Content="{Binding TabContents}" />