Подтвердить что ты не робот

При использовании ItemsControl ItemsControl.ItemsPanel устанавливается в Canvas, ContenPresenter входит и разбивает мои свойства Canvas на дочерних [WPF]

Я использую ItemControl, где для параметра ItemsPanel задано значение Canvas (см. этот вопрос для получения дополнительной информации). Элемент ItemsControl выполняется так, как я хочу, и он работает как шарм при добавлении дочернего элемента вручную, помещая его в ItemControl.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.Left на ContentPresenter? Или есть другой способ решить эту проблему?

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

4b9b3361

Ответ 1

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

  • используйте свойство layout/rendertransform вместо прикрепленного свойства
  • использовать поля вместо прикрепленного свойства
  • выводится из ItemsControl и переопределяет поведение, как генерируются дочерние контейнеры. (GetContainerForItemOverride, IsItemItsOwnContainerOverride). В этой статье очень хорошо объясняется, как это работает: http://drwpf.com/blog/2008/07/20/itemscontrol-g-is-for-generator/

Ответ 2

Можно установить свойство 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

Кнопка

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

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

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

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

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

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