Мне нужно в качестве панели для элементов указать 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
. Исправляем это искусственно.
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Для того, чтобы удалить все элементы подходящие под условие можно использовать метод RemoveAll
При развертывании проекта (чтение sms-сообщений), после получения сообщения приложение открывается три разаПо-моему OnCreate() запускается несколько...
Как завершить tcp соединение для windowsnetworking