I am doing a custom WPF UserControl and i need to draw a variable size text that is rotated 45 degrees and spaced evenly horizontally, like the next image (being the red bars the text):
With the following code:
<UserControl.Resources>
<ResourceDictionary>
<DataTemplate x:Key="CheckTemplate">
<!-- description -->
<TextBlock
VerticalAlignment="Bottom" Margin="-10,0,0,0" Text="{Binding Check.Name}" Background="Transparent" x:Name="AAA">
<TextBlock.LayoutTransform>
<RotateTransform Angle="-45" />
</TextBlock.LayoutTransform>
</TextBlock>
<DataTemplate.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="1">
<Setter Property="Margin" Value="0" TargetName="AAA" />
</Trigger>
</DataTemplate.Triggers>
</DataTemplate>
<ItemsPanelTemplate x:Key="ChecksItemsPanel">
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Left"
VerticalAlignment="Bottom"
/>
</ItemsPanelTemplate>
</ResourceDictionary>
</UserControl.Resources>
<StackPanel x:Name="RootPanel" Margin="5">
<ItemsControl
x:Name="WorkflowChecksItemsControl"
ItemTemplate="{DynamicResource CheckTemplate}"
ItemsPanel="{DynamicResource ChecksItemsPanel}"
ItemsSource="{Binding WorkflowChecks}" />
</StackPanel>
i only managed to do something like this:
How can i do this using XAML?
In this project i am also using Telerik UI for WPF, and i can use theirs framework if it is simpler.
You may combine a -90° LayoutTransform of the ItemsPanel with a 45° RenderTransform of each TextBlock. For the horizontal distance, simply set the TextBlocks' Height.
<ItemsControl ItemsSource="{Binding WorkflowChecks}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel>
<StackPanel.LayoutTransform>
<RotateTransform Angle="-90"/>
</StackPanel.LayoutTransform>
</StackPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Check.Name}" RenderTransformOrigin="0,1">
<TextBlock.RenderTransform>
<RotateTransform Angle="45"/>
</TextBlock.RenderTransform>
</TextBlock>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Result:
Related
I'm struggling with a school project. I'm making a very basic application, that can read the content of a selected folder and display it in a ListView. I've created an interface called IFiles and have three sub-classes named: Image, Text and Folder. They all implement the IFiles interface.
My problem is mostly regarding the design in XAML. Because I want each listview item to have it's own individual color based on what type of object it finds. So if its a Text file, the background color should be green, and if its an image it should be blue. My current solution partially works, but it does paint the entire row as I want it to.
I can indeed choose a color for the ListViewItem, but I only know how to do it for all at once, not for a single row.
This is my code:
<Window.Resources>
<BitmapImage x:Key="ImgIcon" UriSource="/Images/photo.png" DecodePixelHeight="20" DecodePixelWidth="20"></BitmapImage>
<BitmapImage x:Key="TextIcon" UriSource="/Images/textfile.png" DecodePixelHeight="20" DecodePixelWidth="20"></BitmapImage>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="Background" Value="Red"></Setter>
</Style>
<DataTemplate DataType="{x:Type model:Image}">
<StackPanel Orientation="Horizontal" Background="Blue" >
<Image Source="{DynamicResource ImgIcon}"></Image>
<Label Content="Filename:"></Label>
<Label Content="{Binding Name}"></Label>
<Label Content="Size:"></Label>
<Label Content="{Binding Size}"></Label>
</StackPanel>
</DataTemplate>
<DataTemplate DataType="{x:Type model:Text}">
<StackPanel Orientation="Horizontal" Background="Green" >
<Image Source="{DynamicResource TextIcon}"></Image>
<Label Content="Filename:"></Label>
<Label Content="{Binding Name}"></Label>
<Label Content="Size:"></Label>
<Label Content="{Binding Size}"></Label>
</StackPanel>
</DataTemplate>
</Window.Resources>
<Grid>
<Button Content="Load Folder" HorizontalAlignment="Left" Margin="315,355,0,0" VerticalAlignment="Top" Width="155" Height="40" Command="{Binding LoadFolderCMD}"/>
<ListView ItemsSource="{Binding Files}" Margin="0,0,0,89" HorizontalAlignment="Left" Width="792"/>
</Grid>
This is what it looks like when I execute it:
The red part should have the same color as the content inside of the particular row.
Hope you can help me
Set HorizontalContentAlignment="Stretch" on the ListView.
You should also take advantage of grid rows and columns to confine items into separate areas. Avoid using margins for placement, the margins and paddings should be used for defining gap between elements, not their absolute position.
You can make the ItemTemplate fill the available space by setting the HorizontalContentAlignment of the ListViewItem to Stretch and move some padding from it to the data templates:
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="Background" Value="Red"></Setter>
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Padding" Value="0" />
</Style>
<DataTemplate DataType="{x:Type model:Image}">
<Border Background="Blue" Padding="4,1">
<StackPanel Orientation="Horizontal">
<Image Source="{DynamicResource ImgIcon}"></Image>
<Label Content="Filename:"></Label>
<Label Content="{Binding Name}"></Label>
<Label Content="Size:"></Label>
<Label Content="{Binding Size}"></Label>
</StackPanel>
</Border>
</DataTemplate>
<DataTemplate DataType="{x:Type model:Text}">
<Border Background="Green" Padding="4,1">
<StackPanel Orientation="Horizontal">
<Image Source="{DynamicResource TextIcon}"></Image>
<Label Content="Filename:"></Label>
<Label Content="{Binding Name}"></Label>
<Label Content="Size:"></Label>
<Label Content="{Binding Size}"></Label>
</StackPanel>
</Border>
</DataTemplate>
I am binding a PivotItems but somehow the items are not resized properly, according to my margin declaration. Why is that?
EDIT: here is my new code and it still has gaps..
<Pivot x:Name="TpsSegmentsPivot" Title="Locator" Foreground="#FF888888" Style="{StaticResource PivotStyle1}" SelectionChanged="Pivot_SelectionChanged" Margin="0" Grid.Row="1" ItemTemplate="{StaticResource TpTemplate}" ItemsSource="{Binding DataSource}">
<Pivot.HeaderTemplate>
<DataTemplate>
<Grid>
<TextBlock Text="{Binding id}" Margin="0, 16, 0, 0" Foreground="#FF888888" FontSize="32" FontFamily="Segoe WP" FontWeight="Light"/>
</Grid>
</DataTemplate>
</Pivot.HeaderTemplate>
</Pivot>
This is the template:
<DataTemplate x:Key="TpTemplate">
<ListBox Background="Black"
ItemsSource="{Binding Seg}"
ItemTemplate="{StaticResource SectionUCTemplate}"
HorizontalAlignment="Stretch"
VerticalAlignment="Top">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
</DataTemplate>
Here is a screenshot with the red pivotItem..
I think the issue with the extra space is the Piviot Item you are using inside the DataTemplate tag. remove it and bind the header to a header template. I've used data binding on Pivots before and never seen this issue.
From one of my released apps:
<controls:Pivot Title="CAMPING CHECKLIST" ItemsSource="{Binding FilteredCategories}" Name="MainPivot">
<controls:Pivot.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</controls:Pivot.HeaderTemplate>
<controls:Pivot.ItemTemplate>
<DataTemplate>
<!-- Your pivot item content here -->
</DataTemplate>
</controls:Pivot.ItemTemplate>
</controls:Pivot>
I believe the PivotItem in a PivotItem is the root of your issue.
your code should look similar to:
<controls:Pivot ItemsSource="{Binding tripTypeViewModel.TripTypeViewModelDataSource}" x:Name="TripsSegmentsPivot" Title=" " Foreground="#FF888888" Style="{StaticResource PivotStyle1}" SelectionChanged="Pivot_SelectionChanged" Grid.Row="1">
<controls:Pivot.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding DataContext.tripTypeViewModel.HeaderText, ElementName=TripsSegmentsPivot}" Margin="0, 16, 0, 0" Foreground="#FF888888" FontSize="32" FontFamily="Segoe WP" FontWeight="Light"/>
</DataTemplate>
</controls:Pivot.HeaderTemplate>
<controls:Pivot.ItemTemplate>
<DataTemplate>
<ListBox x:Name="ItemsLB" ItemsSource="{Binding DataContext.tripTypeViewModel.Segment, ElementName=TripsSegmentsPivot}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="Transparent">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<local:SectionUC HorizontalAlignment="Stretch" Grid.Row="1" VerticalAlignment="Top"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DataTemplate>
</controls:Pivot.ItemTemplate>
</controls:Pivot>
The first image is how I describe it, the second is how you currently have it :
This is the standard behaviour for PivotItems since they are always displayed with a margin. You should set a negative margin:
margin="-20,0,-20,0"
I am not a WPF expert so please excuse my inappropriate use of terms. I have a ScrollViewer where I am displaying a captured image. And I have a slider with which I am zooming the image in and out. Zooming works fine, but the scrollbars are not changing their size. Hence when the image goes beyond the boundaries, I cannot scroll and view it. As if the scrollbars become useless because they haven't changed their size. Here is my XAML:
The Slider:
<Slider DockPanel.Dock="Right" Width="100" VerticalAlignment="Center" Minimum="0.2" Maximum="5"
Interval="1" Value="{Binding ScaleFactor}"/>
The rest of XAML:
<Border BorderThickness="1" BorderBrush="Black" Grid.Row="1">
<Grid>
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"
CanContentScroll="True">
<ItemsControl ItemsSource="{Binding ItemCollection}" Margin="0"
Width="{Binding Root.Boundary.Width}" Height="{Binding Root.Boundary.Height}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas>
<Canvas.LayoutTransform>
<ScaleTransform ScaleX="{Binding ScaleFactor}"
ScaleY="{Binding ScaleFactor}"CenterX="0" CenterY="0"/>
</Canvas.LayoutTransform>
</Canvas>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Image x:Name="capturedImage"
Source="{Binding Image}"
Width="{Binding Boundary.Width}"
Height="{Binding Boundary.Height}"/>
<Path x:Name="captureContour"
Data="{Binding Outline}"
Stroke="Black" StrokeThickness="4" Opacity="0.5"
StrokeLineJoin="Round">
<Path.LayoutTransform>
<ScaleTransform ScaleX="{Binding OutlineScale.X}"
ScaleY="{Binding OutlineScale.Y}" CenterX="0"CenterY="0"/>
</Path.LayoutTransform>
</Path>
</Grid>
<DataTemplate.Triggers>
<Trigger SourceName="capturedImage" Property="IsMouseOver"
Value="True">
<Setter TargetName="captureContour" Property="Stroke"
Value="Blue"/>
<Setter TargetName="captureContour" Property="BitmapEffect">
<Setter.Value>
<DropShadowBitmapEffect/>
</Setter.Value>
</Setter>
</Trigger>
</DataTemplate.Triggers>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Grid>
</Border>
The issue is due to the Canvas used as ItemsPanel. as Canvas does not expand or collapse with the size of it's children so ScrollViewer does not detect the change.
As a quick solution change the ItemsPanel to Grid. Since your example does not seems to be using Canvas properties i.e. Canvas.Left or Canvas.Top, this change may not make any difference in the appearance.
example
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid HorizontalAlignment="Left" VerticalAlignment="Top">
<Grid.LayoutTransform>
<ScaleTransform ScaleX="{Binding ScaleFactor}"
ScaleY="{Binding ScaleFactor}"
CenterX="0"
CenterY="0" />
</Grid.LayoutTransform>
</Grid>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
make sure to have HorizontalAlignment="Left" VerticalAlignment="Top" in grid otherwise it may appear weird when you zoom.
give it a try and see if this is what you are looking for.
OK guys, here is what needs to be done in order to make it work:
<ItemsControl ItemsSource="{Binding ItemCollection}" Margin="0" Width="{Binding CanvasWidth}"
Height="{Binding CanvasHeight}"/>
I have CanContentScroll property set to True in the parent Scrollviewer. This ScrollViewer is applicable to the entire Window. Now, this ScrollViewer has ItemsControl as its child. Each item in the ItemsControl is templated as an Expander and the content of this Expander contains another ItemsControl embedded in the child ScrollViewer. If I remove the child ScrollViewer, the Window content is scrollable, however, if I put it back in, I'm unable to Scroll.
I need the child ScrollViewer because I am limiting the height of the Expander content. When I scroll, the event is not being fired to the parent ScrollViewer in the Visual Tree. How and by using which event I can bubble it to the parent ScrollViewer in the Visual Tree?
This is my code:
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:behaviors="clr-namespace:AttributeSelector" xmlns:sys="clr-namespace:System;assembly=mscorlib"
MinHeight="350" MinWidth="525" MaxWidth="1200" MaxHeight="900" WindowStartupLocation="CenterScreen" SizeToContent="WidthAndHeight">
<sys:Boolean x:Key="BooleanTrue">True</sys:Boolean>
<sys:Boolean x:Key="BooleanFalse">False</sys:Boolean>
<behaviors:TextToHighlightedTextBlockConverter x:Key="TextToHighlightedTextBlockConverter" />
<behaviors:GroupNameToICollectionViewConverter x:Key="GroupNameToICollectionViewConverter" />
<LinearGradientBrush x:Key="LinearGradientBrush" StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Color="White" Offset="0"/>
<GradientStop Color="#E3E3E3" Offset="1"/>
<!--<GradientStop Color="#C0C0C0" Offset="1"/>-->
</LinearGradientBrush>
<Style x:Key="MainBorderStyle" TargetType="{x:Type Border}">
<Setter Property="Background" Value="{StaticResource ResourceKey=LinearGradientBrush}" />
<Setter Property="BorderBrush" Value="LightGray" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="CornerRadius" Value="5" />
<Setter Property="SnapsToDevicePixels" Value="True" />
</Style>
</Window.Resources>
<DockPanel LastChildFill="True" Margin="10">
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Margin="10">
<!-- 3-4 TextBlocks/TextBoxes defined here -->
</StackPanel>
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" CanContentScroll="True">
<ItemsControl ItemsSource="{Binding UniqueGroups}" ScrollViewer.CanContentScroll="True"
ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel IsItemsHost="True" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Margin="5" Style="{StaticResource ResourceKey=MainBorderStyle}">
<Expander x:Name="GroupExpander" Header="{Binding}" IsExpanded="True" Margin="5">
<Expander.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" Background="Transparent" Margin="10,0,0,0"
FontWeight="DemiBold" FontSize="16" FontStretch="Expanded"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Expander}}, Path=ActualWidth}"/>
</DataTemplate>
</Expander.HeaderTemplate>
<Expander.Content>
<ScrollViewer Margin="20,5,10,5" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto" CanContentScroll="True">
<ItemsControl ItemsSource={Binding SubItems} ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel MaxHeight="300" Orientation="Vertical" UseLayoutRounding="True" IsItemsHost="True" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.GroupStyle>
<GroupStyle>
<GroupStyle.Panel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Horizontal" IsItemsHost="True" />
</ItemsPanelTemplate>
</GroupStyle.Panel>
</GroupStyle>
</ItemsControl.GroupStyle>
</ItemsControl>
</ScrollViewer>
</Expander.Content>
</Expander>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</DockPanel>
I've been using a SemanticZoom containing a GridView in both the ZommedInView and the ZoomedOutView. The one in the ZoomedOutView doesn't seem to snap to the container though. The container is a StackPanel, located in a ScrollViewer. This means that when I zoom out, my items are offscreen if the Horizontal-alignment is set to left.
Also, when I select the zommed-in gridview in the designer, it is clearly shown in the expected place, filling the scrollviewer. The zoomed-out gridview is shown to exceed the boundaries of the page.
Swapping the content of the zoomed-in and zoomed-out views swaps the problem to the other gridview, so we can deduce the problem is not in a difference of the gridview.
Is there a way to fix it or is it a bug in the control?
<ScrollViewer
x:Name="itemGridScrollViewer"
AutomationProperties.AutomationId="ItemGridScrollViewer"
Grid.Row="1"
Margin="0,-3,0,0"
Style="{StaticResource HorizontalScrollViewerStyle}">
<!--
ItemTemplateSelector="{StaticResource hubItemTemplateSelector}"
ItemTemplate="{StaticResource Standard250x250ItemTemplate}"
-->
<StackPanel
Margin="116,0,40,46">
<SemanticZoom ManipulationMode="RotateInertia">
<SemanticZoom.ZoomedInView>
<GridView
AutomationProperties.AutomationId="ItemGridView"
AutomationProperties.Name="Grouped Items"
ItemsSource="{Binding Source={StaticResource groupedItemsViewSource}}"
ItemTemplateSelector="{StaticResource hubItemTemplateSelector}"
SelectionMode="None"
IsItemClickEnabled="True"
ItemClick="ItemView_ItemClick"
IsSwipeEnabled="True">
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
<GridView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<Grid Margin="1,0,0,6">
<Button
AutomationProperties.Name="Group Title"
Content="{Binding Path=Title}"
Click="Header_Click"
Style="{StaticResource TextButtonStyle}"/>
</Grid>
</DataTemplate>
</GroupStyle.HeaderTemplate>
<GroupStyle.Panel>
<ItemsPanelTemplate>
<VariableSizedWrapGrid MaximumRowsOrColumns="2" ItemHeight="250" ItemWidth="250" Orientation="Horizontal"/>
</ItemsPanelTemplate>
</GroupStyle.Panel>
</GroupStyle>
</GridView.GroupStyle>
</GridView>
</SemanticZoom.ZoomedInView>
<SemanticZoom.ZoomedOutView>
<GridView
AutomationProperties.AutomationId="CategoryGridView"
AutomationProperties.Name="Grouped Items Zoomed Out"
ItemsSource="{Binding Path=ItemGroups}"
>
<GridView.ItemTemplate>
<DataTemplate>
<Button
AutomationProperties.Name="Group Title"
Content="{Binding Title}"
Click="Header_Click"
Style="{StaticResource TextButtonStyle}"/>
</DataTemplate>
</GridView.ItemTemplate>
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<WrapGrid ItemWidth="250" ItemHeight="250" MaximumRowsOrColumns="2" VerticalChildrenAlignment="Center" />
</ItemsPanelTemplate>
</GridView.ItemsPanel>
<GridView.ItemContainerStyle>
<Style TargetType="GridViewItem">
<Setter Property="Margin" Value="4" />
<Setter Property="Padding" Value="10" />
<Setter Property="Background" Value="#FF25A1DB" />
<Setter Property="BorderThickness" Value="1" />
</Style>
</GridView.ItemContainerStyle>
</GridView>
</SemanticZoom.ZoomedOutView>
</SemanticZoom>
</StackPanel>
</ScrollViewer>
The solution seems to be to set the HorizontalAlignment attribute on the StackPanel that contains the SemanticZoom. If I set it to Left, the content aligns appropriately.