Пользовательский элемент управления WPF для параллельной компоновки - PullRequest
2 голосов
/ 24 августа 2009

Я хочу создать пользовательский элемент управления, чтобы я мог сделать что-то вроде этого:

<SideBySide>
    <StackPanel SideBySide.Left="True">...</StackPanel>
    <StackPanel SideBySide.Right="False">...</StackPanel>
</SideBySide>

Я собираюсь использовать это повсеместно, с явно большим количеством опций (размер и т. Д.).

Я рассмотрел вопрос об использовании подкласса Panel, но это не совсем верно (существует понятие выбранного элемента между левым и правым).

Итак, я пытаюсь использовать подкласс ItemsControl - теперь, кто-нибудь знает, как поместить элементы в шаблон элемента управления для ItemsControl?

Это сокращенный шаблон для SideBySide:

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfCustomControlLibrary1">
    <Style TargetType="{x:Type local:SideBySideControl}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:SideBySideControl}">
                    <Border Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}">
                        <Grid>
                            <Grid.Resources>
                                <Style TargetType="{x:Type Rectangle}">
                                    <Setter Property="Margin"
                                            Value="5" />
                                </Style>
                            </Grid.Resources>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition />
                                <ColumnDefinition Width="Auto" />
                                <ColumnDefinition />
                            </Grid.ColumnDefinitions>
                            <Grid Grid.Column="0"
                                  VerticalAlignment="Stretch">
                                <!-- PART_LeftContent goes here -->
                            </Grid>
                            <GridSplitter Width="3"
                                          Grid.Column="1"
                                          HorizontalAlignment="Center"
                                          VerticalAlignment="Stretch"
                                          ShowsPreview="False">
                            </GridSplitter>
                            <Grid Grid.Column="2">
                                <!-- PART_RightContent goes here -->
                            </Grid>
                        </Grid>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

1 Ответ

1 голос
/ 26 августа 2009

Прямой ответ: вам нужно ItemsPresenter в вашем ControlTemplate, которое будет выглядеть примерно так:

<ItemsControl x:Class="ItemsControlExample"
              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <ItemsControl.Template>
        <ControlTemplate TargetType="ItemsControl">
            <Border SnapsToDevicePixels="True">
                <!-- Collection items are displayed by the ItemsPresenter. --> 
                <ItemsPresenter SnapsToDevicePixels="True" />
            </Border>
        </ControlTemplate>
    </ItemsControl.Template>

    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <!-- Replace the default vertical StackPanel with horizontal. -->
            <StackPanel Orientation="Horizontal" />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>

    <ItemsControl.ItemContainerStyle>
        <Style TargetType="...">
            <!-- The same container style applies to all items so where do you put the splitter? -->
        </Style>
    </ItemsControl.ItemContainerStyle>    

</ItemsControl>

Но теперь должно быть очевидно, что ItemsControl не соответствует вашему варианту использования. Однако вы можете реализовать его как Control, используя ControlTemplate, который у вас уже есть с ContentControl ячейками сетки PART_LeftContent и PART_RightContent:

<!-- LeftSideContent is a DependencyProperty of type object -->
<ContentControl x:Name="LeftContentControl" Content="{TemplateBinding LeftSideContent}" />

Затем расширьте свой код для обработки событий мыши ContentControl, чтобы выбрать и добавить триггеры стиля для выбранного внешнего вида, но это довольно просто. Если вы не реализовали элементы управления без контроля, прежде чем вы должны знать, что вы не можете определить обратные вызовы событий в шаблоне, а вместо этого должны подключить их в своем коде:

public override void OnApplyTemplate()
{
    base.OnApplyTemplate();

    ContentControl lc = (ContentControl)base.GetTemplateChild("LeftContentControl"));
    // check for null in case the active template doesn't have a 'LeftContentControl' element
    if (lc != null) 
    {
        // Use these events to set SelectedItem DependencyProperty and trigger selected item 
        // highlight style. Don't forget to capture the mouse for proper click behavior.
        lc.MouseDown += new MouseButtonEventHandler(LeftSide_MouseDown);
        lc.MouseUp += new MouseButtonEventHandler(LeftSide_MouseUp);
    }
 }
...