Как "наследовать" от базы xaml - PullRequest
0 голосов
/ 13 января 2019

У меня есть PageViewModelBase, где детям нужно реализовать 3 метода, и все работает, как задумано, и поэтому я хотел бы создать PageViewBase, и его дети реализуют две простые неуниверсальные вещи (а именно: данные столбцы привязки контекста и сетки данных).

Я встречал этот пост и пытался создать базовый 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 голосов
/ 14 января 2019

Вот решение, которое использует программный код для динамического добавления правильных столбцов в 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 с. Однако я не пробовал это в более сложном случае, поэтому заранее прошу прощения, если это не решит вашу конкретную проблему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...