При использовании ItemsControl ItemsControl.ItemsPanel устанавливается значение Canvas, входит ContenPresenter и нарушает мои свойства Canvas для дочерних элементов [WPF] - PullRequest
15 голосов
/ 10 марта 2010

Я использую ItemsControl, где ItemsPanel установлен на Canvas (см. этот вопрос для получения дополнительной информации). ItemsControl работает так, как я хочу, и работает как шарм при добавлении дочернего элемента вручную, помещая его в ItemsControl.Items:

<ItemsControl>
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas IsItemsHost="True" />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.Items>
        <Button Canvas.Left="500" Content="Button Text" />
    </ItemsControl.Items>
</ItemsControl>

Обратите внимание на свойство Canvas.Left для Button. Это работает как брелок, и кнопка расположена на расстоянии 500 пикселей слева от элемента ItemsControl. Отлично!

Однако, когда я определяю привязку ItemsSource к списку, Canvas.left не имеет никакого эффекта:

<ItemsControl ItemsSource="{Binding Elements}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas IsItemsHost="True" />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Button Canvas.Left="500" Content="Button Text" />
        </DataTemplate>     
    </ItemsControl.ItemTemplate>
</ItemsControl> 

Проверяя приложение во время выполнения, я вижу одно отличие. Контейнер ContentPresenter был добавлен между Canvas и кнопкой ..

Как я могу установить свойство Canvas.Left для самого ContentPresenter? Или есть другой способ решить эту проблему?

Спасибо всем!

Ответы [ 3 ]

25 голосов
/ 09 мая 2010

Можно установить свойство Canvas.Left с помощью ItemContainerStyle:

<ItemsControl ItemsSource="{Binding Elements}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Canvas IsItemsHost="True" />
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Button Content="Button Text" />
            </DataTemplate>     
        </ItemsControl.ItemTemplate>
    <ItemsControl.ItemContainerStyle>
        <Style>
             <Setter Property="Canvas.Left" Value="500" />
        </Style>
    </ItemsControl.ItemContainerStyle>
</ItemsControl>
3 голосов
/ 10 марта 2010

Есть несколько решений, которые приходят мне на ум:

  1. использовать макет / rendertransform вместо прикрепленного свойства
  2. использовать маржу вместо прикрепленного свойства
  3. наследуется от ItemsControl и переопределяет поведение генерации дочерних контейнеров. (GetContainerForItemOverride, IsItemItsOwnContainerOverride). Эта статья довольно хорошо объясняет, как это работает: http://drwpf.com/blog/2008/07/20/itemscontrol-g-is-for-generator/
2 голосов
/ 18 января 2013
Кнопка

Не имеет свойства «Canvas», поэтому вы делаете относительный вызов управляющего элемента хостинга, однако, поскольку элемент и холст находятся в разных шаблонах, прямой ссылки нет, поэтому Canvas.Left не имеет смысла перед временем выполнения.

следовательно, ваш метод не может найти левое значение для установки, поэтому теряет изменение.

Однако сеттеры реализуются только во время выполнения, поэтому

<Setter Property="Canvas.Left" Value="500" /> 

будет выполняться только после того, как объекты были сгенерированы, и, следовательно, имеют относительные отношения.

В противном случае вы можете использовать поле, которое принадлежит объекту кнопки, но опять-таки интерпретируется только во время выполнения

...