Scrolling Image: the drawing shapes cover the scroller - how to fix it? - c#

My View displays the image as a first layer, than I display the bunch of the shapes (rectangles, lines, circles) over the image as a second layer.
The image has a scroller because it can't be fully displayed on my View.
The strange issue is enclosed in the fact, that the shapes are displayed over the scroller.
How can I fix it?
Here's my View:
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="500" />
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="500" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<ScrollViewer VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Visible">
<Image Source="{Binding VM.ManipulatedImage}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Stretch="None"
Width="Auto" Height="Auto"/>
</ScrollViewer>
<ItemsControl
ItemsSource="{Binding VM.Shapes, Mode=TwoWay}"
Grid.Row="0" Grid.Column="0">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Path Data="{Binding Geometry}"
Fill="{Binding Fill}"
Stroke="{Binding Stroke}"
StrokeThickness="{Binding StrokeThickness}"
Opacity="{Binding Opacity}"
/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>

Place the ScrollViewer around the Grid. The Grid is happy to have multiple children.
<ScrollViewer VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Visible">
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="500" />
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="500" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Image Source="{Binding VM.ManipulatedImage}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Stretch="None"
Width="Auto" Height="Auto"/>
<ItemsControl
ItemsSource="{Binding VM.Shapes, Mode=TwoWay}"
Grid.Row="0" Grid.Column="0">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Path Data="{Binding Geometry}"
Fill="{Binding Fill}"
Stroke="{Binding Stroke}"
StrokeThickness="{Binding StrokeThickness}"
Opacity="{Binding Opacity}"
/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</ScrollViewer>

Related

ItemsControl with row and column headers WPF

I need to represent updatable list ObservableCollection<RegisterBean> listOfRegisters of objects RegisterBean as matrix with row and column headers Object contain 3 properties:
byte deviceAddress;
byte register;
byte[] data;
And only one property data should be displayed.
The expected result is like on image:
I reached this structure with usual datagrid but the problem was to update it because I used a converter with new DataTable() as a returned value. This is not correct because it flickers and rerenders all objects.
I asked for a help yesterday here. And this solution is working:
<ItemsControl ItemsSource="{Binding listOfRegisters}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="16"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding Data, Converter={StaticResource ByteToStringValueConverter}}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
But I didn't understand how to change the structure of usercontrol and to add headers. The result of the solution with itemscontrol:
Thanks!
UPD:
The headers should be static without any sorting and stuff like that
I start saying that probably, checking what's wrong with DataGrid would be better and that is not necessary to re-write Controls, but if you still want to use the ItemsControl ...
Supposing that there are two collections (ColHeaders & RowHeaders) in your ViewModel that contains your Headers you can add two other panels that hold headers..
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<!-- Column Headers -->
<ItemsControl Grid.Column="1" Grid.Row="0" ItemsSource="{Binding ColHeaders}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding}" Width="30" Height="30"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<ItemsControl Grid.Row="1" Grid.Column="1" ItemsSource="{Binding listOfRegisters}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="16"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding Data, Converter={StaticResource ByteToStringValueConverter}}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<!-- RowHeaders -->
<ItemsControl Grid.Column="0" Grid.Row="1" ItemsSource="{Binding RowHeaders}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding}" Width="30" Height="30"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
I also sized the TextBlocks and the TextBoxes in order to align everything.
Just add a Grid around it, like this:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid Grid.Row="0" Grid.Column="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Content="Col 0"/>
<Label Grid.Column="1" Content="Col 1"/>
<Label Grid.Column="2" Content="Col 2"/>
</Grid>
<Grid Grid.Row="1" Grid.Column="0">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Label Grid.Row="0" Content="Row 0"/>
<Label Grid.Row="1" Content="Row 1"/>
<Label Grid.Row="2" Content="Row 2"/>
</Grid>
<UniformGrid Rows="3" Columns="3" Grid.Column="1" Grid.Row="1">
<Button Content="00"/>
<Button Content="01"/>
<Button Content="02"/>
<Button Content="10"/>
<Button Content="11"/>
<Button Content="12"/>
<Button Content="20"/>
<Button Content="21"/>
<Button Content="22"/>
</UniformGrid>
</Grid>

Horizontal scroll GridView Windows Phone 8.1

I have the following XAML file. I am trying to make my images to scroll horizontal.
It doesn't work, what might be wrong?
<DataTemplate x:Key="SampleDataTemplate">
<Grid Margin="0,0,0,10">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<GridView ScrollViewer.HorizontalScrollBarVisibility="Visible" ScrollViewer.HorizontalScrollMode="Enabled">
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<WrapGrid Orientation="Horizontal"></WrapGrid>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
<Image x:Name="templateImage" Source="{Binding ItemImage}" />
</GridView>
</Grid>
</DataTemplate>

Extracting data templates in user controls

There are known problems for setting up caliburn binding in DataTemplates.
In this answer EisenbergEffect suggests extracting Data Templates into a user control.
How can this be achieved?
In my user control I have lots of DataTemplates and ran into those problems. Conventions are not applied and I have to use "classical" Binding.
I could only imagine to extract the whole control with the DataTemplate, this would give me lots of smaller controls, but I see no way to only extract the DataTemplate.
Here is an example XAML
<Grid>
<Grid.Resources />
<Grid.RowDefinitions>
<RowDefinition Height="10*" />
<RowDefinition Height="2*" />
<RowDefinition Height="1*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<Border HorizontalAlignment="Stretch"
BorderBrush="Transparent"
BorderThickness="0">
<ScrollViewer HorizontalContentAlignment="Stretch"
Background="Yellow"
BorderBrush="Transparent"
BorderThickness="0"
CanContentScroll="True"
HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto">
<!-- Conventions work here -->
<ListView x:Name="Computers"
HorizontalContentAlignment="Stretch"
Background="Red"
BorderThickness="0">
<ListView.ItemTemplate>
<DataTemplate>
<Border Background="Transparent"
BorderBrush="Transparent"
BorderThickness="0">
<ListView HorizontalContentAlignment="Stretch"
Background="Black"
ItemsSource="{Binding HardwareComponents}"> <!-- Conventions to not work here -->
<ListView.ItemTemplate>
<DataTemplate>
<Border Background="Aquamarine"
BorderBrush="DarkGray"
BorderThickness="1">
<Grid Background="Transparent" cal:Message.Attach="[Event MouseDown] = [Action Expand($dataContext)]" >
<Grid.RowDefinitions>
<RowDefinition Height="20" />
</Grid.RowDefinitions>
<Border BorderBrush="Red" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<!-- Even more DataTemplates come here -->
</Border>
</Grid>
</Border>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Border>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ScrollViewer>
</Border>
</Grid>

ScrollViewer does not react to the Grid.Row position

My StackPanel and ScrollViewer seem to just not end at the Grid.Row position. I am making a Metro app so it is mandatory for the grid to be dynamic, as well as all the elements.
The code:
<Grid Background="#FFE4E4E4">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.5*"/>
<ColumnDefinition Width="0.5*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="0.5*"/>
<RowDefinition Height="0.5*"/>
</Grid.RowDefinitions>
<!--News/Leaderboard Feed-->
<StackPanel Grid.Column="0" Grid.Row="0">
</StackPanel>
<!--Marketplace Feed-->
<StackPanel Grid.Column="0" Grid.Row="1">
</StackPanel>
<!--Detailed Marketplace Account-->
<StackPanel Grid.Column="1" Grid.Row="1">
</StackPanel>
<!--Marketplace View-->
<StackPanel Grid.Column="1" Grid.Row="0" VerticalAlignment="Top">
<ScrollViewer VerticalAlignment="Top">
<!--Allows scrolling-->
<GridView x:Name="MarketplaceFeed" ItemsSource="{Binding StockList}" ItemTemplate="{StaticResource MarketplaceFeedTemplate}" VerticalAlignment="Top">
<!--Displays the stock markets the user is interested in.-->
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<WrapGrid Orientation="Horizontal" />
</ItemsPanelTemplate>
</GridView.ItemsPanel>
</GridView>
</ScrollViewer>
</StackPanel>
</Grid>
You should put the ScrollViewer on the outside. This will auto-fit to the grid, and anything inside it will get the scrolling treatment.
<!--Marketplace View-->
<ScrollViewer VerticalAlignment="Top" Grid.Column="1" Grid.Row="0">
<StackPanel VerticalAlignment="Top">
<!-- other content -->
</StackPanel>
</ScrollViewer>

WPF DataGrid Scrollbar

I'm trying to make a WPF DataGrid show scrollbars when necessary.
You can see the basic XAML code of my user control below:
<Grid x:Name="Data" Grid.Column="0" VerticalAlignment="Stretch" Height="Auto" HorizontalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Expander Header="Route Setup" Grid.Row="0" VerticalAlignment="Top" Background="White">
</Expander>
<Expander Header="Select Locations" Grid.Row="1" VerticalAlignment="Top" Background="White">
</Expander>
<DataGrid Grid.Row="2" ItemsSource="{Binding Locations, Mode=TwoWay}" Height="Auto" AutoGenerateColumns="False" ScrollViewer.CanContentScroll="True"
ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.HorizontalScrollBarVisibility="Auto">
</DataGrid>
This isn't working, I don't see any scroolbars when the DataGrid grows beyond the available space. I've already tried to use a scrollview around my DataGrid but that doesn't change anything.
Update
It might be important to know that the usercontrol is loaded into the LeftRegion of a shell that has the following markup:
<Grid x:Name="LayoutRoot">
<Grid.ColumnDefinitions >
<ColumnDefinition Width="*" MinWidth="400" MaxWidth="600"/>
<ColumnDefinition Width="9" />
<ColumnDefinition Width="*" MinWidth="300" />
</Grid.ColumnDefinitions>
<GridSplitter x:Name="MainSplitter" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" Grid.Column="1"
Margin="0" Width="9" Style="{DynamicResource gridSplitterVerticalStyle}"/>
<ItemsControl Name="LeftRegion" Grid.Column="0" Background="Azure" Height="Auto" VerticalAlignment="Stretch" VerticalContentAlignment="Stretch" cal:RegionManager.RegionName="LeftRegion">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
<ItemsControl Name="RightRegion" Height="Auto" Background="DarkGreen" VerticalAlignment="Stretch" VerticalContentAlignment="Stretch" Grid.Column="2" cal:RegionManager.RegionName="RightRegion">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</Grid>
Best Regards
Jay
In your grid named "Data", remove the Height="Auto" from the third RowDefinition. At least one row must have the "*" height (which is the default) to take the remaining available space.
Solved it. I needed to remove Height="Auto" from the thrird RowDefinition.

Categories

Resources