Мне нужно в качестве панели для элементов указать Canvas и подключить возможность перемещать элементы в ней.
Есть вот такая разметка.
<ItemsControl ItemsSource="{Binding MapObjects}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas IsItemsHost="True"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<ContentControl Content="{Binding}">
<i:Interaction.Behaviors>
<behaviors:DragBehavior/>
</i:Interaction.Behaviors>
</ContentControl>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Left" Value="{Binding Position.X}"/>
<Setter Property="Canvas.Top" Value="{Binding Position.Y}"/>
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
Из разметки видно, что для того, чтобы биндиться к аттачед свойствам Canvas.Top/Left понадобилось делать биндинг через стиль ContentPresenter, потому что каждый элемент оборачивается в ContentPresenter. А вот Behaviors я через стили указать не могу, потому что дизайнер ругается вот таким матом
Свойство Behaviors не является DependencyProperty
Пробовал сделать так
<Setter Property="i:Interaction.Behaviors">
<Setter.Value>
<behaviors:DragBehavior/>
</Setter.Value>
</Setter>
А в том виде, в котором это сейчас, оно не работает, потому что AssociatedObject в коде DragBehavior у меня является ContentControl. Я, конечно, могу найти нужный мне элемент по визуальному дереву, но что то мне подсказывает, что есть более изящный способ, который не будет так жестко привязан к разметке
Нашел решение здесь http://stackoverflow.com/a/4779168/5938996
Вот что получилось
<ItemsControl ItemsSource="{Binding MapObjects}">
<ItemsControl.Resources>
<local:MyBehaviors x:Key="myBehaviors" x:Shared="False">
<behaviors:DragBehavior/>
</local:MyBehaviors>
</ItemsControl.Resources>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas IsItemsHost="True"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<ContentControl Content="{Binding}">
</ContentControl>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Left" Value="{Binding X, Mode=TwoWay}"/>
<Setter Property="Canvas.Top" Value="{Binding Y, Mode=TwoWay}"/>
<Setter Property="local:SupplementaryInteraction.Behaviors" Value="{StaticResource myBehaviors}"/>
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
И код
public class MyBehaviors : List<Behavior>
{
}
public static class SupplementaryInteraction
{
public static MyBehaviors GetBehaviors(DependencyObject obj)
{
return (MyBehaviors)obj.GetValue(BehaviorsProperty);
}
public static void SetBehaviors(DependencyObject obj, MyBehaviors value)
{
obj.SetValue(BehaviorsProperty, value);
}
public static readonly DependencyProperty BehaviorsProperty =
DependencyProperty.RegisterAttached("Behaviors", typeof(MyBehaviors), typeof(SupplementaryInteraction), new UIPropertyMetadata(null, OnPropertyBehaviorsChanged));
private static void OnPropertyBehaviorsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var behaviors = Interaction.GetBehaviors(d);
foreach (var behavior in e.NewValue as MyBehaviors) behaviors.Add(behavior);
}
}
Если кратко, Behaviors не является DependencyProperty. Исправляем это искусственно.
Сборка персонального компьютера от Artline: умный выбор для современных пользователей