DevExpress - MVVM - 使用不同的ViewModel生成TabItems

时间:2014-06-24 09:18:33

标签: c# wpf xaml devexpress tabcontrol

我有一个DXTabControl。 DXTabItems是通过我的ViewModel生成的。

// MainViewModel

public MainViewModel()
{
    var items = new ObservableCollection<DXTabItem>();
    items.Add(
        new DXTabItem()
        {
            Header = "Test1",
            Content = new WebViewModel()
        });

    items.Add(
        new DXTabItem()
        {
            Header = "Test2",
            Content = new CMSViewModel()
        });

    TabItems = items;
}

private ObservableCollection<DXTabItem> _tabItems;
public ObservableCollection<DXTabItem> TabItems
{
    get { return _tabItems; }
    set { SetProperty(ref _tabItems, value, () => TabItems); }
}

我正在使用DataTemplate,我的TabItem仍未显示任何UserControl。

// MainView.xaml

<DataTemplate x:Key="WebTemplate" DataType="{x:Type viewmodel:WebViewModel}">
    <view:WebView/>
</DataTemplate>

<DataTemplate x:Key="CMSTemplate" DataType="{x:Type viewmodel:CMSViewModel}">
    <view:CMSView/>
</DataTemplate>

<datatemplate:TemplateSelector x:Key="DataTemplateSelector" 
                        WebTemplate="{StaticResource WebTemplate}"
                        CMSTemplate="{StaticResource CMSTemplate}" />

<dx:DXTabControl ItemsSource="{Binding TabItems}" ItemTemplateSelector="{StaticResource DataTemplateSelector}" />

// DataTemplateSelector

public class TemplateSelector : DataTemplateSelector
{
    public DataTemplate WebTemplate { get; set; }
    public DataTemplate CMSTemplate { get; set; }

    public override DataTemplate SelectTemplate(Object item,
        DependencyObject container)
    {

        if (item == null) return base.SelectTemplate(item, container);

        if (item.GetType() == typeof(WebViewModel))
        {
            return WebTemplate;
        }

        else if (item.GetType() == typeof(CMSViewModel))
        {
            return CMSTemplate;
        }

        else return base.SelectTemplate(item, container);

    }
}

除了显示我需要的内容外,一切正常。没有显示任何视图。任何的想法?我错过了什么吗?

1 个答案:

答案 0 :(得分:0)

以下答案基于caliburn.micro。

步骤1:向引导程序添加约定

public Bootstrapper()
{
ConventionManager.AddElementConvention<DXTabControl>(DXTabControl.ItemsSourceProperty, "ItemsSource", "DataContextChanged")
            .ApplyBinding = (viewModelType, path, property, element, convention) =>
        {
            if (!ConventionManager.SetBindingWithoutBindingOrValueOverwrite(viewModelType, path, property, element, convention, DXTabControl.ItemsSourceProperty))
            {
                return false;
            }
            var tabControl = (DXTabControl)element;
            if (tabControl.ItemTemplate == null && tabControl.ItemTemplateSelector == null && property.PropertyType.IsGenericType)
            {
                var itemType = property.PropertyType.GetGenericArguments().First();
                if (!itemType.IsValueType && !typeof(string).IsAssignableFrom(itemType))
                {
                    tabControl.ItemTemplate = ConventionManager.DefaultItemTemplate;
                }
            }

            ConventionManager.ConfigureSelectedItem(element, Selector.SelectedItemProperty, viewModelType, path);

            if (string.IsNullOrEmpty(tabControl.DisplayMemberPath))
            {
                ConventionManager.ApplyHeaderTemplate(tabControl, DXTabControl.ItemHeaderTemplateProperty, DXTabControl.ItemHeaderTemplateSelectorProperty, viewModelType);
            }
            return true;
        };

[...]
}

现在您可以将任何Screen-Collection绑定到DXTabControl。

第2步:在ViewModel中创建一个集合

public class MainViewModel : Screen
{
    public MainViewModel()
    {
        DisplayName = "DevExpress Test Environment";
    }


    private static BindableCollection<Screen> _tbCtrl = new BindableCollection<Screen>();
    public BindableCollection<Screen> TbCtrl
    {
        get { return _tbCtrl; }
        set
        {
            _tbCtrl = value;
            NotifyOfPropertyChange(() => TbCtrl);
        }
    }
}

你可以,例如将基于Screen类的任何其他ViewModel放到您的集合中。这意味着,您将能够显示每个tabitem的内容。

步骤3:在视图中创建DXTabControl(XAML-Code)

<dx:DXTabControl x:Name="TbCtrl" />

试一试。打开反馈。

///没有Caliburn.Micro的替代解决方案

步骤1:将DXTabControl添加到MainView(XAML-Code)

<dx:DXTabControl ItemsSource="{Binding TbCtrlItems}" />

第2步:你的MainViewModel需要添加我上面描述过的那些项目(在我的问题中),但在这种情况下,你必须指定content-property

public MainViewModel()
    {
        _tbCtrlItems.Add(new DXTabItem()
        {
            Header = "Test1",
            Content = new Views.View1() {DataContext = new ViewModel1()}
        });

        _tbCtrlItems.Add(new DXTabItem()
        {
            Header = "Test2",
            Content = new Views.View2() { DataContext = new ViewModel2() }
        });


    }

    private ObservableCollection<DXTabItem> _tbCtrlItems = new ObservableCollection<DXTabItem>();

    public ObservableCollection<DXTabItem> TbCtrlItems
    {
        get { return _tbCtrlItems; }
        set { SetProperty(ref _tbCtrlItems, value, () => TbCtrlItems); }
    }

我希望这个答案很有帮助。