Silverlight 3 - Положение привязки данных прямоугольника на холсте

В настоящее время я пытаюсь привязать коллекцию объектов к Canvas в Silverlight 3 с помощью ItemsControl, как показано ниже:

<ItemsControl x:Name="ctrl" ItemsSource="{Binding myObjectsCollection}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas></Canvas>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Rectangle Stroke="LightGray" Fill="Black"  StrokeThickness="2" 
                   RadiusX="15" RadiusY="15" Canvas.Left="{Binding XAxis}"
                   Height="25" Width="25">
            </Rectangle>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

К сожалению, похоже, что привязка Canvas.Left игнорируется. Из того, что я узнал здесь, похоже, это связано с элементами помещается в презентатор контента, а не в фактический холст, который я указал на панели элементов.

Есть ли способ использовать привязку данных для определения положения элементов на холсте?


person Blounty    schedule 28.10.2009    source источник


Ответы (5)


Я понимаю, что для этого уже есть принятый ответ, но способ достичь первоначальной цели, не вмешиваясь в поля, - это создать настраиваемый ItemsControl и переопределить метод PrepareContainerForItemOverride. В этом методе привязка устанавливается в коде.

public class CustomItemsCollection
    : ItemsControl
{
    protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
    {

        FrameworkElement contentitem = element as FrameworkElement;
        Binding leftBinding = new Binding("Left"); // "Left" is the property path that you want to bind the value to.
        contentitem.SetBinding(Canvas.LeftProperty, leftBinding);

        base.PrepareContainerForItemOverride(element, item);
    }

}
person Tom    schedule 12.11.2009

Вы не можете использовать ItemsControl.ItemContainerStyle в Silverlight. Его не существует. Он существует только на нескольких классах конечного уровня, таких как сам ListBox.

person DMC    schedule 06.04.2010

Вы правы, ContentPresenter вставлен между Canvas и Rectangle. Одним из обходных путей было бы установить левое поле вместо Canvas.Left:

<Rectangle Stroke="LightGray" Fill="Black" StrokeThickness="2" 
      RadiusX="15" RadiusY="15" Height="25" Width="25">
    <Rectangle.Margin>
        <Thickness Left="{Binding XAxis}"/>
    </Rectangle.Margin>
</Rectangle>
person Mart    schedule 28.10.2009
comment
К сожалению, свойство Left доступно только для чтения и не может быть установлено. - person Blounty; 29.10.2009
comment
Я не знаю, почему он доступен только для чтения. Как бы то ни было, мне удалось добиться этого с помощью преобразователя значений: ‹Rectangle ... Margin = {Binding XAxis, Converter = {StaticResource LeftMarginConverter}} /›, но это определенно не изящное решение. - person Mart; 29.10.2009
comment
Как работает LeftMarginConverter, и когда он применяется, применяется ли поле ко всем связанным элементам относительно левого края контейнера? - person Blounty; 30.10.2009
comment
Это преобразователь: открытый класс LeftMarginConverter: IValueConverter {открытый объект Convert (значение объекта, тип targetType, параметр объекта, культура CultureInfo) {возвращает новое значение толщины ((int), 0, 0, 0); } открытый объект ConvertBack (значение объекта, тип targetType, параметр объекта, культура CultureInfo) {throw new NotImplementedException (); }} Таким образом устанавливается левое смещение. Если вы выполняете привязку с Margin = {Binding}, вы можете представить себе любое другое позиционирование, основанное на свойствах вашего объекта. - person Mart; 30.10.2009

Я знаю, что этот вопрос немного устарел, но вы можете просто использовать преобразование рендеринга - я делаю нечто подобное;

<ItemsControl ItemsSource="{Binding Notes}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas Background="Aqua"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>

    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Border Width="{Binding W}" Height="{Binding H}" BorderBrush="Navy" BorderThickness="5" CornerRadius="10">
                <TextBlock Text="{Binding Text}"/>
                <Border.RenderTransform>
                    <TransformGroup>
                        <RotateTransform Angle="0"/>
                        <TranslateTransform X="{Binding X}" Y="{Binding Y}"/>
                    </TransformGroup>
                </Border.RenderTransform>
            </Border>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>
person deepcode.co.uk    schedule 27.01.2011

Добавьте следующее в свой ItemsControl

 <ItemsControl.ItemContainerStyle>
    <Style TargetType="{x:Type ContentPresenter}">
      <Setter Property="Canvas.Left" Value="{Binding XPath=XAxis}"/>
    </Style>
  </ItemsControl.ItemContainerStyle>

Нет необходимости в каких-либо настраиваемых элементах управления

person Nat    schedule 14.03.2010
comment
Это не может работать, поскольку ItemsControl не имеет свойства ItemContainerStyle в Silverlight (v3 или v4). В WPF да, но вопрос не в этом. - person Anthony; 12.07.2010