Как использовать Canvas как ItemsPanel для ItemsControl в Silverlight 3
Я пытаюсь установить свойства Canvas в ItemsControl DataTemplate с Silverlight 3. Согласно этот пост, единственный способ сделать это - установить его с помощью ItemsContainerStyle для типа ContentPresenter, так как свойства Canvas действуют только на прямых дочерних элементов Canvas. Это, похоже, не работает в SL3, поскольку ItemControl не имеет свойства ItemsContainerStyle, поэтому я попробовал ListBox по рекомендации этой статьи, но он все равно не работает. Из XAML ниже я ожидал бы увидеть зеленый квадрат с цифрами 10, 30, 50, 70, каскадом от "NW" до "SE". Может ли кто-нибудь сказать мне, почему все они сложены на вершине eachother в углу NW?
<UserControl x:Class="TestControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:System="clr-namespace:System;assembly=mscorlib" >
<StackPanel>
<ListBox>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Background="Green" Width="100" Height="100" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding}" />
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Left" Value="{Binding}" />
<Setter Property="Canvas.Top" Value="{Binding}" />
</Style>
</ListBox.ItemContainerStyle>
<ListBox.Items>
<System:Int32>10</System:Int32>
<System:Int32>30</System:Int32>
<System:Int32>50</System:Int32>
<System:Int32>70</System:Int32>
</ListBox.Items>
</ListBox>
</StackPanel>
</UserControl>
Ответы
Ответ 1
Я не уверен, что он будет работать в вашем сценарии, но в прошлом я делал это с использованием RenderTransform.
<ItemsControl>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Background="Green" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding}">
<TextBox.RenderTransform>
<TranslateTransform X="100" Y="100" />
</TextBox.RenderTransform>
</TextBox>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.Items>
<System:Int32>10</System:Int32>
<System:Int32>30</System:Int32>
<System:Int32>50</System:Int32>
<System:Int32>70</System:Int32>
</ItemsControl.Items>
</ItemsControl>
Или в случае привязки вам нужно будет использовать конвертер
<ItemsControl>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Background="Green" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding}" RenderTransform="{Binding Converter={StaticResource NumberToTransformGroupConverter}}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.Items>
<System:Int32>10</System:Int32>
<System:Int32>30</System:Int32>
<System:Int32>50</System:Int32>
<System:Int32>70</System:Int32>
</ItemsControl.Items>
</ItemsControl>
Преобразователь
public void ConvertTo(object value, ...)
{
int intValue = int.Parse(value.ToString());
return new TransformGroup()
{
Children = new TransformCollection()
{
new TranslateTransform { X = intValue, Y = intValue }
}
};
}
Ответ 2
Silverlight4 не привязывается к прикрепленным свойствам в стиле. Я предлагаю использовать подход Дэвида Ансона, описанный здесь.
<UserControl.Resources>
<Style x:Key="ScreenBindStyle" TargetType="ListBoxItem">
<Setter Property="Helpers:SetterValueBindingHelper.PropertyBinding">
<Setter.Value>
<Helpers:SetterValueBindingHelper>
<Helpers:SetterValueBindingHelper Type="Canvas" Property="Left" Binding="{Binding LocationField.Value.X}" />
<Helpers:SetterValueBindingHelper Type="Canvas" Property="Top" Binding="{Binding LocationField.Value.Y}" />
<Helpers:SetterValueBindingHelper Type="Canvas" Property="ZIndex" Binding="{Binding ZIndex.Value}" />
</Helpers:SetterValueBindingHelper>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<ContentPresenter/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
И в списке:
ItemContainerStyle="{StaticResource ScreenBindStyle}"
Ответ 3
Старый пост, но я пошел в ту же проблему, но теперь с SL5, которая теперь позволяет Binding
в настройках стиля. Я пытался избежать использования ListBox
(потому что он обрабатывает выбор и т.д.), А ItemsControl
по-прежнему не имеет ItemContainerStyle
. Поэтому я попробовал несколько вещей.
Я не нашел много вопросов, обсуждающих эту проблему, поэтому позвольте мне поделиться своим решением (извините, если он дублирует)
На самом деле, я нашел очень удобный способ решить проблему, добавив в ресурс ItemsControl
неназванный Style
:
<ItemsControl ItemsSource="{Binding Path=MyData}">
<ItemsControl.Resources>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Top" Value="{Binding Path=Bounds.Top}"/>
<Setter Property="Canvas.Left" Value="{Binding Path=Bounds.Left}"/>
<Setter Property="Width" Value="{Binding Path=Bounds.Width}"/>
<Setter Property="Height" Value="{Binding Path=Bounds.Height}"/>
</Style>
</ItemsControl.Resources>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="my:DataType">
...
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Работает как шарм в SL5:)
Ответ 4
Я не могу объяснить, что вы видите. Ваш Xaml разбит, по крайней мере, несколькими способами.
Сначала сам Xaml терпит неудачу, потому что это: -
<Style TargetType="ContentPresenter">
должен быть
<Style TargetType="ContentControl">
Контейнеры Item в случае ListBox
имеют тип ListBoxItem
, которые выводятся из ContentControl
.
Тем не менее, размещение {Binding} в настройках стиля по-прежнему не работает. Думаю, вы предполагали, что стиль будет применяться к каждому элементу поочередно и получить его значение из текущего элемента. Однако, даже если привязка работала в стиле, существовал бы только стиль один, и он получил бы привязку данных из ListBox DataContext
. Это другой DataContext
, который применяется к каждому элементу ListBox (который в этом случае является каждым элементом в коллекции Items).
Тем не менее, я думаю, что у Бен есть разумное решение, которое устраняет этот подход.