在WPF MVVM中动态创建TabControl和子网格

时间:2016-02-11 18:03:36

标签: wpf mvvm

我有一个使用Devexpress作为第三方工具的wpf mvvm应用程序。我需要动态创建包含datagrids的选项卡。我想知道这样做的最佳做法是什么。我已经创建了一个包含选项卡和内容模板的视图

         <TabControl ItemsSource="{Binding Workspaces}">
        <TabControl.ContentTemplate>
            <DataTemplate>
                <DataGrid ItemsSource="{Binding Data}" AutoGenerateColumns="False">
                    <DataGrid.Columns >
                        <DataGridTextColumn Header="Column 1" Binding="{Binding Column1}" />
                        <DataGridTextColumn Header="Column 2" Binding="{Binding Column2}" />
                        <DataGridTextColumn Header="Column 3" Binding="{Binding Column3}" />
                    </DataGrid.Columns>
                </DataGrid>
            </DataTemplate>
        </TabControl.ContentTemplate>
    </TabControl>

我的观点模型

  public class DataTest
{
    public string Column1 { get; set; }
    public string Column2 { get; set; }
    public string Column3 { get; set; }
}


public abstract class WorkspaceViewModel 
{
    public String HeaderText { get; set; }
    public override string ToString()
    {
        return HeaderText;
    }
    //ObservableCollection
    public ObservableCollection<DataTest> Data { get; set; }

}


public class FirstUserControlViewModel : WorkspaceViewModel
{
    public FirstUserControlViewModel()
    {
        base.HeaderText = "My First Tab";
        Data = new ObservableCollection<DataTest>();
        for (int i = 0; i < 5; i++)
        {
            Data.Add(new DataTest()
                        {
                            Column1 = "1st Test" + i.ToString(),
                            Column2 = "1st Test" + i.ToString(),
                            Column3 = "1st Test" + i.ToString()
                        }); 
        }
    }
}


public class SecondUserControlViewModel : WorkspaceViewModel
{
    public SecondUserControlViewModel()
    {
        base.HeaderText = "My Second Tab";
        Data = new ObservableCollection<DataTest>();
        for (int i = 0; i < 5; i++)
        {
            Data.Add(new DataTest()
            {
                Column1 = "2nd Test" + i.ToString(),
                Column2 = "2nd Test" + i.ToString(),
                Column3 = "2nd Test" + i.ToString()
            });
        }
    }
}

public class ThirdUserControlViewModel : WorkspaceViewModel
{
    public ThirdUserControlViewModel()
    {
        base.HeaderText = "My Third Tab";
        Data = new ObservableCollection<DataTest>();
        for (int i = 0; i < 5; i++)
        {
            Data.Add(new DataTest()
            {
                Column1 = "3rd Test" + i.ToString(),
                Column2 = "3rd Test" + i.ToString(),
                Column3 = "3rd Test" + i.ToString()
            });
        }
    }
}

public class ViewModel
{

    private ObservableCollection<WorkspaceViewModel> _workspaces;

    public ObservableCollection<WorkspaceViewModel> Workspaces
    {
        get
        {
            if (_workspaces == null)
            {
                _workspaces = new ObservableCollection<WorkspaceViewModel>();
            }
            return _workspaces;
        }
    }


    public ViewModel()
    {
        Workspaces.Add(new FirstUserControlViewModel());
        Workspaces.Add(new SecondUserControlViewModel());
        Workspaces.Add(new ThirdUserControlViewModel());
    }

}

这已经有效但我想知道是否有更好的方法。我应该将datagrid放在usercontrol中并传递其参数Data。我也在这个应用程序中使用Prism是否有可以利用的东西有益处?

1 个答案:

答案 0 :(得分:0)

这将有效,但前提是所有选项卡都要显示完全相同的控件,并且网格显示完全相同的数据结构。

如果你想要其他控件或数据,我建议使用隐式new = collection.update([<a whole bunch of documents], upsert=True) return new.results # or similar 而不是硬编码DataTemplates

ContentTemplate

通过这种方式,您可以将每个工作空间设置为任何对象模型(可能具有共享接口,因此存在将标题文本绑定到的公共属性),并且可以以任何方式绘制每个选项卡。

<TabControl ItemsSource="{Binding Workspaces}">
    <TabControl.Resources>
        <!-- Draw WorkspaceAViewModel with WorkspaceAView -->
        <DataTemplate TargetType="{x:Type local:WorkspaceAViewModel}">
            <local:WorkspaceAView />
        </DataTemplate>

        <!-- Draw WorkspaceBViewModel with WorkspaceBView -->
        <DataTemplate TargetType="{x:Type local:WorkspaceBViewModel}">
            <local:WorkspaceBView />
        </DataTemplate>

        <!-- Draw WorkspaceCViewModel with WorkspaceCView -->
        <DataTemplate TargetType="{x:Type local:WorkspaceCViewModel}">
            <local:WorkspaceCView />
        </DataTemplate>
    </TabControl.ContentTemplate>
</TabControl>