【问题标题】:DevExpress - MVVM - Generate TabItems with different ViewModelsDevExpress - MVVM - 使用不同的 ViewModel 生成 TabItems
【发布时间】:2014-06-24 09:18:33
【问题描述】:

我有一个 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}" />

//数据模板选择器

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);

    }
}

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

【问题讨论】:

  • 你有没有得到这个答案?我今天在使用 DevExpress v14.1 时遇到了同样的问题。
  • 嗯,是的,有点。我正在与 caliburn.micro 合作,你也是吗?明天我在办公室时,我可以尝试为您提供答案。目前,我正在使用智能手机。
  • 我试图弄清楚如何让用户控件出现在选项卡项中(不是标题,而是内容区域)。不适用于 caliburn.micro。
  • 哦,如果你正在使用 caliburn.micro,我会给你一些有用的东西 ;) 给我一些时间 ^^
  • 我的错,我把你的“不使用 caliburn.micro”解释错了。我对此感到抱歉。你应该试试看。它使您的生活更轻松。没有caliburn.micro,我不确定,但它应该是可行的。还没看呢。

标签: c# wpf xaml devexpress tabcontrol


【解决方案1】:

以下答案基于 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 代码)

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

试一试。公开征求意见。

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

第 1 步:将 DXTabControl 添加到您的 MainView(XAML 代码)

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

我希望这个答案会有所帮助。

【讨论】:

    猜你喜欢
    • 2018-09-04
    • 2021-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多