based on ItemsControl only shows first Item of each object I need your help again. The solution worked out very well but after vacation and doing other stuff I need to modify it.
Actually there are Objects (CanvasObject) which are drawn on startup/after reading xml data and others (Module) which are dropped into the canvas from a treeview. These Modules are showing up in the canvas visual children but I cant see them at the canvas.
This is my code so far - I tried different approaches but always got similar results:
C#:
public class CanvasLine
{
public Point P1 { get; set; }
public Point P2 { get; set; }
public Brush Stroke { get; set; }
public double StrokeThickness { get; set; }
public DoubleCollection StrokeDashArray { get; set; }
}
public class CanvasObject
{
public String Name { get; set; }
public ObservableCollection<CanvasLine> CanvasLines { get; set; }
}
public class Module
{
public Dictionary<String, String> Attributes { get; set; }
public Point AnchorPoint { get; set; }
public Double Height { get; set; }
public Double Width { get; set; }
}
public class ViewModel
{
...
public ObservableCollection<Object> CanvasObjects;
...
}
The Viewmodels ObservableCollection<Object>
gets filled with CanvasObjects from a xml - these ones are shown correctly. After that I'm adding Modules to that Collection by dropping them to the canvas. These ones seems to be into the canvas children collection but are not visible.
Here is the corresponding / cleaned up XAML:
<ItemsControl Grid.Column="1" Grid.Row="2" Margin="0" ItemsSource="{Binding CanvasObjects, UpdateSourceTrigger=PropertyChanged}">
<ItemsControl.Resources>
<ScaleTransform x:Key="LineTransform"
ScaleX="{Binding ActualWidth,
RelativeSource={RelativeSource AncestorType=ItemsControl}}"
ScaleY="{Binding ActualWidth,
RelativeSource={RelativeSource AncestorType=ItemsControl}}"/>
</ItemsControl.Resources>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Background="Transparent" AllowDrop="True" Drop="Canvas_OnDrop"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplateSelector>
<xmlTemp:TemplateSelector>
<xmlTemp:TemplateSelector.ModuleTemplate>
<DataTemplate DataType="{x:Type xmlElements:Module}">
<ItemsControl ItemsSource="{Binding RelativeSource={RelativeSource Self}}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Left" Value="{Binding AnchorPoint.X}"/>
<Setter Property="Canvas.Top" Value="{Binding AnchorPoint.Y}"/>
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Rectangle Width="{Binding Width}" Height="{Binding Height}" StrokeThickness="2" Fill="Black" Stroke="Black">
<Rectangle.RenderTransform>
<StaticResource ResourceKey="LineTransform"/>
</Rectangle.RenderTransform>
</Rectangle>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
</xmlTemp:TemplateSelector.ModuleTemplate>
<xmlTemp:TemplateSelector.LineObjectTemplate>
<DataTemplate DataType="{x:Type dt:CanvasObject}">
<ItemsControl ItemsSource="{Binding CanvasLines}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Path Stroke="{Binding Stroke}"
StrokeDashArray="{Binding StrokeDashArray}">
<Path.Data>
<LineGeometry
Transform="{StaticResource LineTransform}"
StartPoint="{Binding P1}"
EndPoint="{Binding P2}"/>
</Path.Data>
<Path.Style>
<Style TargetType="Path">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="StrokeThickness">
<Setter.Value>
<MultiBinding Converter="{StaticResource MultiplicationConverter}">
<Binding Path="StrokeThickness" Mode="OneWay"/>
<Binding Source="3"/>
</MultiBinding>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsMouseOver" Value="False">
<Setter Property="StrokeThickness" Value="{Binding StrokeThickness, Mode=OneWay}"/>
</Trigger>
</Style.Triggers>
</Style>
</Path.Style>
</Path>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
</xmlTemp:TemplateSelector.LineObjectTemplate>
</xmlTemp:TemplateSelector>
</ItemsControl.ItemTemplateSelector>
</ItemsControl>
Here are the missing event and template selector:
private void Canvas_OnDrop(Object sender, DragEventArgs e)
{
Module Module = e.Data.GetData("Module") as Module;
Canvas Canvas = sender as Canvas;
if (Module != null && Canvas != null)
{
Module.Width = 0.1;
Module.Height = 0.2;
Module.AnchorPoint = e.GetPosition(Canvas);
ViewModel.CanvasObjects.Add(Module);
}
}
public class TemplateSelector : DataTemplateSelector
{
public DataTemplate LineObjectTemplate { get; set; }
public DataTemplate ModuleTemplate { get; set; }
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
if (item is CanvasObject)
return LineObjectTemplate;
if (item is Module)
return ModuleTemplate;
return base.SelectTemplate(item, container);
}
}
If I'm changing the ModuleTemplates ItemsControl to a ListBox I can see at least that there is some selected element in the top left corner after dropping a Module somewhere in the canvas. I'm thinking that the Rectangles Container might have no size but I'm not sure how to handle that correctly. Also the dropping position has no effect.
Possibly it's just a stupid error, just like the transparent, not dropable/hitable background which costs me over an hour today and I'm "seeing" it tomorrow after a few hours of sleep but every help and hint is highly appreciated!
Greetings
Edit:
THX to elgonzo I found the error. The Modules ItemsControl was unnecessary! THX again, perfect time to finish work now ;)
Following Code works fine:
<ItemsControl Grid.Column="1" Grid.Row="2" Margin="0" ItemsSource="{Binding CanvasObjects, UpdateSourceTrigger=PropertyChanged}">
<ItemsControl.Resources>
<ScaleTransform x:Key="LineTransform"
ScaleX="{Binding ActualWidth,
RelativeSource={RelativeSource AncestorType=ItemsControl}}"
ScaleY="{Binding ActualWidth,
RelativeSource={RelativeSource AncestorType=ItemsControl}}"/>
</ItemsControl.Resources>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Background="Transparent" AllowDrop="True" Drop="Canvas_OnDrop"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplateSelector>
<xmlTemp:TemplateSelector>
<xmlTemp:TemplateSelector.ModuleTemplate>
<DataTemplate DataType="{x:Type xmlElements:Module}">
<DataTemplate.Resources>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Left" Value="{Binding AnchorPoint.X}"/>
<Setter Property="Canvas.Top" Value="{Binding AnchorPoint.Y}"/>
</Style>
</DataTemplate.Resources>
<Rectangle Width="{Binding Width}" Height="{Binding Height}" StrokeThickness="2" Fill="Black" Stroke="Black">
<Rectangle.RenderTransform>
<StaticResource ResourceKey="LineTransform"/>
</Rectangle.RenderTransform>
</Rectangle>
</DataTemplate>
</xmlTemp:TemplateSelector.ModuleTemplate>
<xmlTemp:TemplateSelector.LineObjectTemplate>
<DataTemplate DataType="{x:Type dt:CanvasObject}">
<ItemsControl ItemsSource="{Binding CanvasLines}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Path Stroke="{Binding Stroke}"
StrokeDashArray="{Binding StrokeDashArray}">
<Path.Data>
<LineGeometry
Transform="{StaticResource LineTransform}"
StartPoint="{Binding P1}"
EndPoint="{Binding P2}"/>
</Path.Data>
<Path.Style>
<Style TargetType="Path">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="StrokeThickness">
<Setter.Value>
<MultiBinding Converter="{StaticResource MultiplicationConverter}">
<Binding Path="StrokeThickness" Mode="OneWay"/>
<Binding Source="3"/>
</MultiBinding>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsMouseOver" Value="False">
<Setter Property="StrokeThickness" Value="{Binding StrokeThickness, Mode=OneWay}"/>
</Trigger>
</Style.Triggers>
</Style>
</Path.Style>
</Path>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
</xmlTemp:TemplateSelector.LineObjectTemplate>
</xmlTemp:TemplateSelector>
</ItemsControl.ItemTemplateSelector>
</ItemsControl>