如何从基础xaml

时间:2019-01-13 15:13:45

标签: c# wpf xaml inheritance

我有一个PageViewModelBase,孩子需要实现3种方法,一切都按预期进行,因此,我想创建PageViewBase并让其孩子实现两个简单的非泛型事物(即:数据上下文绑定和数据网格列)。

我遇到过this post,并试图相应地创建基本xaml(如下代码),但是尽管方法不同,但我无法创建子视图。我尝试过<baseView:PageViewBase>是xaml中的唯一元素,并将其嵌入到另一个UserControl中,但是两种方法都失败了。

基本视图(省略了很多噪声代码,添加了子视图必须实现以实现可视化的示例部分):

<UserControl x:Class="WPFapp.Views.Base.PageViewBase">
    <UserControl.Resources>
        <!--<DataTemplate DataType="{x:Type localVM:HardwareViewModel}">
            <local:HardwareView/>
        </DataTemplate>-->
        <localHelpers:DateTimeConverter x:Key="dateTimeConverter" />
        <localHelpers:StatusColorConverter x:Key="statusColorConverter" />
    </UserControl.Resources>
    <UserControl.InputBindings> </UserControl.InputBindings>
    <Grid Margin="10">
        <Grid.RowDefinitions>
            <RowDefinition Height="1*" MinHeight="25" />
            <RowDefinition Height="15*" />
        </Grid.RowDefinitions>
        <ToolBarPanel Grid.Row="0" Orientation="Horizontal">
        </ToolBarPanel>

        <DataGrid ItemsSource="{Binding ItemsList}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}" Grid.Row="1" AutoGenerateColumns="False" SelectionMode="Single">
            <DataGrid.ContextMenu> </DataGrid.ContextMenu>
            <DataGrid.InputBindings> </DataGrid.InputBindings>
            <DataGrid.Resources> </DataGrid.Resources>
            <DataGrid.RowStyle> </DataGrid.RowStyle>
            <ContentPresenter ContentSource="Content"/>
            <!--<DataGrid.Columns>
                <DataGridTextColumn Header="LastModifiedBy" Binding="{Binding LastModifiedBy}" />
            </DataGrid.Columns>-->
        </DataGrid>
    </Grid>
</UserControl>

子视图:

<UserControl x:Class="WPFapp.Views.HardwareView">
    <UserControl.Resources>
        <DataTemplate DataType="{x:Type localVM:HardwareViewModel}">
            <local:HardwareView/>
        </DataTemplate>
    </UserControl.Resources>
    <baseView:PageViewBase>
        <DataGrid>
            <DataGrid.Columns>
                <DataGridTextColumn Header="Id" Binding="{Binding Id}" />
                <DataGridTextColumn Header="Type" Binding="{Binding Type}" />
                <DataGridTextColumn Header="Label" Binding="{Binding Label}" />
                <DataGridTextColumn Header="Description" Binding="{Binding Description}" />
                <DataGridTextColumn Header="LastModifiedBy" Binding="{Binding LastModifiedBy}" />
                <DataGridTextColumn Header="LastModifiedAt" Binding="{Binding LastModifiedAt, Converter={StaticResource dateTimeConverter}}" />
            </DataGrid.Columns>
        </DataGrid>
    </baseView:PageViewBase>
</UserControl>

上面的孩子的xaml代码是到目前为止我所管理的最好的代码,但最终只显示列(例如,从基础上没有工具栏),并且从基础视图中看不到UserControl.Resources。我该如何运作?

1 个答案:

答案 0 :(得分:0)

这是一个使用后台代码将正确的列动态添加到DataGrid的解决方案。您只需要PageViewBase视图,因此您可能要重命名它,因为它不会成为任何内容的“基础”。

UserControl.Resources中,添加跨所有不同模型的所有可能的DataGrid列。例如,

<UserControl.Resources>
    <!-- Converters -->
    <localHelpers:DateTimeConverter x:Key="dateTimeConverter" />
    <localHelpers:StatusColorConverter x:Key="statusColorConverter" />

    <!-- DataGrid Columns -->
    <DataGridTextColumn x:Key="IdColumn" Header="Id" Binding="{Binding Id}" />
    <DataGridTextColumn x:Key="TypeColumn" Header="Type" Binding="{Binding Type}" />
    <DataGridTextColumn x:Key="LabelColumn" Header="Number" Binding="{Binding Label}" />
    <DataGridTextColumn x:Key="LastModifiedColumn" Header="LastModifiedAt" Binding="{Binding LastModifiedAt, Converter={StaticResource dateTimeConverter}}" />
    <!-- More column definitions go here for all model types -->
</UserControl.Resources>

确保将列放在转换器之后,以便可以在数据绑定中使用它们。现在,修改DataGrid,使其在加载时运行后台代码。另外,删除ContentPresenter

<DataGrid
    ItemsSource="{Binding ItemsList}"
    SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
    Grid.Row="1"
    AutoGenerateColumns="False"
    SelectionMode="Single"
    Loaded="DataGrid_OnLoaded"
    >
    <DataGrid.ContextMenu> </DataGrid.ContextMenu>
    <DataGrid.InputBindings> </DataGrid.InputBindings>
    <DataGrid.Resources> </DataGrid.Resources>
    <DataGrid.RowStyle> </DataGrid.RowStyle>
    <!-- Columns are loaded in code-behind -->
</DataGrid>

在后面的代码中,根据绑定到特定视图的视图模型类型(通过视图的DataGrid获得)添加正确的DataContext列:

private void DataGrid_OnLoaded(object sender, RoutedEventArgs e)
{
    if (sender is DataGrid dataGrid)
    {
        if (DataContext is HardwareViewModel)
        {
            dataGrid.Columns.Add(Resources["IdColumn"] as DataGridColumn);
            dataGrid.Columns.Add(Resources["TypeColumn"] as DataGridColumn);
            // More columns added here
        }
        else if (DataContext is AnotherHardwareViewModel)
        {
            dataGrid.Columns.Add(Resources["IdColumn"] as DataGridColumn);
            dataGrid.Columns.Add(Resources["LabelColumn"] as DataGridColumn);
            dataGrid.Columns.Add(Resources["LastModifiedColumn"] as DataGridColumn);
            // More columns added here
        }
    }
}

最后,创建PageViewBase的人都需要将其绑定到所需的视图模型,以获取所需的特定类型。例如,

<StackPanel>
    <local:PageViewBase DataContext="{Binding HardwareViewModel}" />
    <local:PageViewBase DataContext="{Binding AnotherHardwareViewModel}" />
</StackPanel>

我已经针对一种简单的情况测试了该解决方案,并且在两个DataGrid中正确地获得了不同的列集。但是,我还没有在更复杂的情况下尝试过此操作,因此如果无法解决您的特定问题,我会向您道歉。

相关问题