Связывание внутри тела шаблона XAML UserControl - PullRequest
0 голосов
/ 30 апреля 2020

У меня есть UserControl, который я использую для создания простого CardView, как вы могли бы найти в наборе инструментов Dev Express. Он состоит только из заголовка и тела. Тело - это <ContentPresenter/>, которое связывается со свойством зависимости Body элемента управления.

Вот XAML для UserControl

<UserControl x:Class="TwinAxis.UI.WPF.Controls.CardControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:TwinAxis.UI.WPF.Controls"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <UserControl.Resources>
        <Style TargetType="TextBlock" x:Key="SensorStateLabelStyle">
            <Setter Property="FontSize" Value="18" />
        </Style>
        <Style x:Key="CardHeader" TargetType="Border" BasedOn="{StaticResource HeaderStyle}">
            <Setter Property="Height" Value="35" />
        </Style>
    </UserControl.Resources>
    <Grid x:Name="LayoutRoot">
        <Border BorderBrush="DarkSlateGray" BorderThickness="1" Background="White">
            <Border.BitmapEffect>
                <DropShadowBitmapEffect Color="{StaticResource WindowsMediaMainColor}"
                                        ShadowDepth="3"
                                        Direction="315"
                                        Softness="0.45"
                                        Opacity="0.75"/>
            </Border.BitmapEffect>
        </Border>

        <Border>
            <DockPanel>
                <Border DockPanel.Dock="Top" Style="{StaticResource CardHeader}">
                    <TextBlock Style="{StaticResource HeaderText}"
                               DockPanel.Dock="Top"
                               Padding="5"
                               Text="{Binding Header}" />
                </Border>
                <ScrollViewer HorizontalScrollBarVisibility="Auto"
                              Padding="5"
                              VerticalScrollBarVisibility="Auto">
                    <ContentPresenter Content="{Binding Body}" />
                </ScrollViewer>
            </DockPanel>
        </Border>
    </Grid>
</UserControl>

Код CardControl.xaml.cs, стоящий за

public partial class CardControl : UserControl {

    public static readonly DependencyProperty BodyProperty =
        DependencyProperty.Register(nameof(Body), typeof(object), typeof(CardControl), new PropertyMetadata());

    public static readonly DependencyProperty HeaderProperty =
        DependencyProperty.Register(nameof(Header), typeof(string), typeof(CardControl), new PropertyMetadata());

    public CardControl() {
        InitializeComponent();
        LayoutRoot.DataContext = this;
    }

    public object Body {
        get => GetValue(BodyProperty);
        set => SetValue(BodyProperty, value);
    }

    public string Header {
        get => (string)GetValue(HeaderProperty);
        set => SetValue(HeaderProperty, value);
    }

}

Если я использую его, как показано ниже, он прекрасно работает

<!-- Works -->
<ctrl:CardControl Header="Test">
    <ctrl:CardControl.Body>
        <Grid><!-- XAML inside grid --></Grid>
    </ctrl:CardControl.Body>
</ctrl:CardControl>
<!-- Nothing in the body even though I have data templates setup properly -->
<ctrl:CardControl Header="Test">
    <ctrl:CardControl.Body>
        <ContentPresenter Content="{Binding MachineViewModel}" />
    </ctrl:CardControl.Body>
</ctrl:CardControl>

Что я делаю не так? Output

1 Ответ

0 голосов
/ 01 мая 2020

Благодаря @Clemens и @ A Sh в комментариях я смог исправить проблему, переместив весь этот «шаблонный» код в соответствующий тег <Style /> для свойства Template UserControl. Я также удалил принудительно изолированный DataContext, который был упомянут в комментариях, и теперь я могу заполнить содержимое CardControl и сделать так, чтобы он отображался так, как я хотел.

<UserControl x:Class="TwinAxis.UI.WPF.Controls.CardControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:TwinAxis.UI.WPF.Controls"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <UserControl.Resources>
        <Style TargetType="TextBlock" x:Key="SensorStateLabelStyle">
            <Setter Property="FontSize" Value="18" />
        </Style>
        <Style x:Key="CardHeader" TargetType="Border" BasedOn="{StaticResource HeaderStyle}">
            <Setter Property="Height" Value="35" />
        </Style>
        <Style TargetType="local:CardControl">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="local:CardControl">
                        <Grid>
                            <Border BorderBrush="DarkSlateGray" BorderThickness="1" Background="White">
                                <Border.BitmapEffect>
                                    <DropShadowBitmapEffect Color="{StaticResource WindowsMediaMainColor}"
                                                            ShadowDepth="3"
                                                            Direction="315"
                                                            Softness="0.45"
                                                            Opacity="0.75"/>
                                </Border.BitmapEffect>
                            </Border>

                            <Border>
                                <DockPanel>
                                    <Border DockPanel.Dock="Top" Style="{StaticResource CardHeader}">
                                        <TextBlock Style="{StaticResource HeaderText}"
                                                   DockPanel.Dock="Top"
                                                   Padding="5"
                                                   Text="{TemplateBinding Header}" />
                                    </Border>
                                    <ScrollViewer HorizontalScrollBarVisibility="Auto"
                                                  Padding="5"
                                                  VerticalScrollBarVisibility="Auto">
                                        <ContentPresenter Content="{TemplateBinding Content}"/>
                                    </ScrollViewer>
                                </DockPanel>
                            </Border>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </UserControl.Resources>
</UserControl>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...