I've been building a dragable nodes tree using items control and the final hurdle is that the children of the nodes, the ones that are in the items control are not able to be dragged separately for some reason. The root nodes can be dragged on there own so the dragging canvas is working.
This is a picture of the ui, showing the root nodes and the child nodes that are attached together:
This is the visual tree, it shows that the child nodes are attached to a dragable canvas:
The code itself is
<pnl:DragCanvas>
<ContentControl cal:View.Model="{Binding Root}"/>
<ContentControl cal:View.Model="{Binding Root}"/>
</pnl:DragCanvas>
<pnl:DragCanvas x:Name="CurrCanvas">
<ItemsControl ItemsSource="{Binding Children}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<pnl:DragCanvas IsItemsHost="True"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Left" Value="{Binding Path=XPos}"/>
<Setter Property="Canvas.Top" Value="{Binding Path=YPos}"/>
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<ContentControl cal:View.Model="{Binding}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</pnl:DragCanvas>
I've got no idea how to fix it and it's really annoying!!
Related
I have the following XAML in wpf
<Canvas>
<ItemsControl ItemsSource="{Binding CompositeCollection}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.Resources>
<DataTemplate DataType="{x:Type Type1}">
<Shape1/>
</DataTemplate>
<DataTemplate DataType="{x:Type type2}">
<Shape2/>
</DataTemplate>
</ItemsControl.Resources>
</ItemsControl>
</Canvas>
So essentially I have two different data templates for the two different types my System.Windows.Data.CompositeCollection may contain. Either Shape1 or Shape2 is then drawn based on the type.
I need the zindex for shape1 to be higher than shape2, so I need to set the zindex from the dataTemplate.
How would I do this?
The elements in the ItemTemplate will not become direct child elements of the Canvas in the ItemsPanelTemplate. Hence setting something like
<DataTemplate DataType="{x:Type Type1}">
<Shape1 Panel.ZIndex="1"/>
</DataTemplate>
will have no effect.
You would instead have to declare an ItemContainerStyle:
<ItemsControl ...>
...
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Panel.ZIndex" Value="{Binding ViewModelItemZIndex}"/>
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
I want to archive a vertical ListView that contains a UserControl in which i have some infos on the left and a second ListView that will scroll horizontal.
The problem is that my second listview will not start to scroll. It seems to pick unlimited space.
First of all some more infos about my setup:
My window is arranged via a grid basically just a row on top with text and the first listview in the second row.
The first listview uses a ItemTamplate like the following:
<ListView.ItemTemplate>
<DataTemplate>
<controls:MyControl />
</DataTemplate>
</ListView.ItemTemplate>
Beside that it has a ItemContainerStyle to display a horizontal line between the items:
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem"
BasedOn="{StaticResource {x:Type ListViewItem}}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListViewItem">
<StackPanel>
<Rectangle x:Name="Separator"
Height="2"
SnapsToDevicePixels="True"
Fill="{DynamicResource AccentColorBrush}" />
<ContentPresenter />
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
(trigger that disables the unnecessary first line omitted)
MyControl is a UserControl which is also just a grid first column some text and second column is my second listview.
This one is special because it is horizontal. Since their are various approaches for this from arround the internet i will show the one i ended using with.
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Horizontal"
IsItemsHost="True"
IsVirtualizing="True"/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
Item template is again a UserControl (at the moment just a TextBlock) and again the separator lines but this time vertically.
The problem is now that the second ListView is not scrollable. Even if i explicit set them to be visible they are disabled (also after resizing window).
My approach solving this was binding MaxWidth of Stackpanel in ListViewItem Template to Actual with of my MetroWindow.
MaxWidth="{Binding Path=ActualWidth, RelativeSource={RelativeSource AncestorType={x:Type metroControls:MetroWindow}}}"
But this and some other tries binding different sizes of different items does not work.
Can somebody give a hint to resolve this?
I am working on some XAML where I have a RibbonComboBox:
<RibbonComboBox SelectionBoxWidth="150" Grid.Row="0">
<RibbonGallery SelectedItem="{Binding SelectedUtilityRun, Mode=TwoWay}">
<RibbonGalleryCategory ItemsSource="{Binding UtilityRunLabels}" />
</RibbonGallery>
</RibbonComboBox>
When it displays, it shows the items horizontally rather than vertically as I expected:
How do I style it to place the items vertically?
Try setting RibbonGallery.MaxColumnCount to 1:
<RibbonGallery ... MaxColumnCount="1">
Set ItemsPanel in Style and Set Orientation=Vertical
<Style TargetType="RibbonComboBox">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical"
VerticalAlignment="Center"
HorizontalAlignment="Center"/>
</ItemsPanelTemplate>
</Setter.Value>
I hope this will help.
I have the grid with wpf map control and canvas over it for drawing markers over map.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<UserControl Grid.Row="0" Content="{Binding CurrentMap}" />
<UserControl Grid.Row="0" Content="{Binding DrawningCanvas}" />
</Grid>
Now I needed to use more than 1 layer over the map.
What wpf control I should use for binding to ObservableCollection<Canvas> in DataContext and draw them all over each other?
You seem to be somewhat confused. An ObservableCollection is a collection for data items. A Canvas is a UI control. Therefore, you should never have a data item collection with UI elements in.
Instead, you could have a Marker data class that contains X and Y properties for the marker's positions and maybe Name and ImageSource properties to define what it would look like in the UI. Then you could have a ObservableCollection of type Marker named Markers that you could bind to the ItemsSource property of an ItemsControl. Finally, you could set a Canvas as the ItemsPanel of the ItemsControl:
<ItemsControl ItemsSource="{Binding Markers}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Left" Value="{Binding X}"/>
<Setter Property="Canvas.Top" Value="{Binding Y}"/>
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type YourXmlNamespacePrefix:Marker}">
<StackPanel Orientation="Horizontal">
<Image Source="{Binding ImageSource}" />
<TextBlock Text="{Binding Name}" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
I don't really know why you would want to have multiple layers because you could overlay multiple items on the same layer, but if you really need multiple layers, then you can just add more of the ItemsControl elements shown above.
I was wondering if its possible to somehow bind a list of lists to a cavas panel. For example having object "layer" which itself is a list of "rectangle" objects. Would if be possible to bind a list of layers to a canvas? So far I can only do it by binding a flattened INumerable of the nested list (using SelectMany function) to an itemcontrol, but this isnt good enough, Id like to keep the "layers" separate and have the Zindex of the rectangles vary according to the layer it is at, allowing to reorder the layers easily.
I have also tried having nested itemcontrols but as expected it only displays the first layer. The aim is to draw a rectangle for every object in every layer on the canvas allowing for layer manipulation, insertion of new objects in each layer, etc...
Thanks in advance! :)
How about making the ItemTemplate of the main ItemsControl another ItemsControl with yet another Canvas as ItemsPanel? (I do not see a reason why it should only display the first layer)
Actually the main ItemsControl does not need to be a Canvas, a Grid would do as well (at least unless your collections have coordinates of their own or a Z-Order, if you use a grid the layer order is he same as their appearance in the collection).
An example (a bit verbose but can't do anything about that):
<ItemsControl ItemsSource="{Binding Data}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<ItemsControl ItemsSource="{Binding LayerItems}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="{x:Type ContentPresenter}">
<!-- Here would the binding to some properties that take care of placement -->
<Setter Property="Canvas.Top" Value="{Binding Top}" />
<Setter Property="Canvas.Left" Value="{Binding Left}" />
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<!-- Some template for the individual items -->
<DataTemplate>
<Border Padding="5" BorderThickness="1" BorderBrush="Red" CornerRadius="3"
Background="White">
<TextBlock Text="{Binding Name}" />
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Like H.B said, i too can't see a reason why it will not work. Having an ItemsControl in another ItemsContainer works perfectly fine.
<ItemsControl ItemsSource="{Binding Layers}">
<ItemsControl.ItemsContainerStyle>
<Style>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<ItemsControl ItemsSource="{Binding Rectangles}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<ItemsControl.ItemsContainerStyle>
</ItemsControl>
But it think it would be cleaner to put the sub ItemsControl inside an DataTemplate for your Items, without the need to modify the ItemsContainerStyle. I think its bad design if your control needs to know informations about the properties of the model, which is necessary for binding to Rectangles.