Fluid like movement to the items in ItemsControl - c#

I am trying to implement a graph nodes something similar to the graph observed in http://audiomap.tuneglue.net/. (To get graph here Enter some text (ex: asd) in the search box. You will get a relationship graph.)
I could build the graph with a set of nodes and i can move them around. But the issue is I want to make fluid movement to other node while a node is dragged. I tried Expression Blend FluidMoveBehaviour. But it didn't fit perfectly like what i wanted.
Here is my XAML code:
<Window x:Class="SpicyNodes.MainWindow" Name="MainWindow1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:viewModel="clr-namespace:SpicyNodes.ViewModels"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:local="clr-namespace:SpicyNodes"
Title="MainWindow" Height="500" Width="500">
<Window.Resources>
<local:GraphItemDataTemplateSelector x:Key="graphItemDataTemplateSelector" ></local:GraphItemDataTemplateSelector>
<CompositeCollection x:Key="Col">
<CollectionContainer Collection="{Binding DataContext.Connectors,Source={x:Reference MainWindow1}}"/>
<CollectionContainer Collection="{Binding DataContext.Nodes,Source={x:Reference MainWindow1}}"/>
</CompositeCollection>
<DataTemplate x:Key="personTemplate" DataType="{x:Type viewModel:Person}">
<Thumb DragDelta="Thumb_Drag" DragCompleted="thumb_DragCompleted" DragStarted="thumb_DragStarted" Name="thumb"
>
<Thumb.Template>
<ControlTemplate TargetType="Thumb">
<Canvas Margin="-10,-10,10,10">
<Ellipse Height="20" Width="20" Stroke="#696969" StrokeThickness="1" Fill="#353520"
x:Name="Ellipse">
</Ellipse>
<TextBlock Canvas.Top="-20" Canvas.Left="-40" Width="100" FontFamily="Cambria" FontSize="12"
TextAlignment="Center" Text="{Binding Name}"
IsHitTestVisible="False"
/>
</Canvas>
<ControlTemplate.Triggers>
<Trigger Property="IsDragging" Value="True">
<Setter TargetName="Ellipse" Property="Fill" Value="Green"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Thumb.Template>
</Thumb>
</DataTemplate>
<DataTemplate x:Key="connectorTemplate" DataType="{x:Type viewModel:Connector}">
<StackPanel>
<Line Stroke="Gray" StrokeThickness="2"
X1="{Binding StartNode.X}" Y1="{Binding StartNode.Y}"
X2="{Binding EndNode.X}" Y2="{Binding EndNode.Y}" x:Name="Line">
</Line>
</StackPanel>
</DataTemplate>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="1*"></RowDefinition>
<RowDefinition Height="0.2*"></RowDefinition>
</Grid.RowDefinitions>
<ItemsControl
ItemTemplateSelector="{StaticResource graphItemDataTemplateSelector}"
Name="items" ItemsSource="{StaticResource Col}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate x:Name="PanelTemplate">
<Canvas Name="canvas1" >
<!--<i:Interaction.Behaviors>
<ei:FluidMoveSetTagBehavior Tag="Element" AppliesTo="Children"/>
</i:Interaction.Behaviors>-->
</Canvas>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="Canvas.Left" Value="{Binding X}" />
<Setter Property="Canvas.Top" Value="{Binding Y}" />
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
<Button Grid.Row="1" Click="Button_Click" Height="30" Width="50">Add</Button>
</Grid>
And MainWindow.cs file contains:
void _CreateObjectOnCanvas(string Name, double X, double Y)
{
Person node2 = new Person(Name, "", "");
node2.Position = new Point(150, 120);
node2.X = X;
node2.Y = Y;
viewModel.Nodes.Add(node2);
Connector c = new Connector();
c.StartNode = viewModel.Nodes[0];
c.EndNode = node2;
viewModel.Connectors.Add(c);
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Random rand = new Random();
var Angle = rand.Next(0, 360);
Angle = (Angle * 7) % 360;
var X = viewModel.Nodes[0].X + 100 * Math.Sin(Angle);
var Y = viewModel.Nodes[0].Y + 100 * Math.Cos(Angle);
if (!_CheckForOverlap(X, Y))
{
var Person = viewModel.CreatePerson(GIndex++);
_CreateObjectOnCanvas(Person.Name, X, Y);
}
}
Person class contains the following:
double x;
public override double X
{ get { return x; }
set
{
x = value;
OnPropertyChanged("X");
}
}
double y;
public override double Y
{
get { return y; }
set
{
y = value;
OnPropertyChanged("Y");
}
}
public string Name { get; set; }
public string Occupation { get; set; }
public string ContactInfo { get; set; }
public System.Windows.Point Position { get; set; }
public Person(string name, string occupation, string contact)
{
this.Name = name;
this.Occupation = occupation;
this.ContactInfo = contact;
}
Any help in this regard is greatly appreciated as i spent almost 2 days working on this.
Thank you.

Related

How to display the LoginPage before viewing the program?

I created the Login Entities (Login.cs) and also I created Logins property of type DbSet of Login to save logins with (SubBVDbContext.cs) as public DbSet<Login> Logins { get; set;}, then I seed entries into the Login table in the (Configuration.cs) in Migration Folder. After that, I created the (LoginPageViewModel.cs) which includes LoginWrapper that wraps up all entities, as well as the (NavigationView.xaml) that allows navigation from model to another. I have already created (MainViewModel.cs), and the MainWindow.xaml that contain the views of the models and the navigations between them.
What I want is to display the LoginPage first then show the other views.
Login.cs
public class Login
{
public int Id { get; set; }
[Required]
[StringLength(50)]
[EmailAddress]
public string Email { get; set; }
[Required]
public string Password { get; set; }
}
LoginDetailView.xaml(UserControl)
<StackPanel Orientation="Horizontal">
<TextBox Text="{Binding Login.Email, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<PasswordBox PasswordChar="{Binding Login.Password, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>
<Button Width="100" ToolTip="Login to Subcontractors" HorizontalAlignment="Center" Content="login"/>
NavigationViewModel.xaml (UserControl)
<UserControl.Resources>
<Style x:Key="NaviItemContainerStyle" TargetType="ContentPresenter">
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="Margin" Value="2"/>
</Style>
<DataTemplate x:Key="NaviItemTemplate">
<Button Content="{Binding DisplayMember}"
Command="{Binding OpenDetailViewCommand}">
<Button.Template>
<ControlTemplate TargetType="Button">
<Grid x:Name="grid">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="FontWeight" Value="Bold"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Foreground" Value="DarkRed"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
</DataTemplate>
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="300"/>
<RowDefinition/>
</Grid.RowDefinitions>
<GroupBox Header="Subcontarctors">
<ScrollViewer VerticalScrollBarVisibility="Auto"
HorizontalScrollBarVisibility="Auto">
<ItemsControl ItemsSource="{Binding Subs}"
ItemContainerStyle="{StaticResource NaviItemContainerStyle}"
ItemTemplate="{StaticResource NaviItemTemplate}"/>
</ScrollViewer>
</GroupBox>
<GroupBox Header="POs" Grid.Row="1" >
<ScrollViewer VerticalScrollBarVisibility="Auto"
HorizontalScrollBarVisibility="Auto" >
<ItemsControl ItemsSource="{Binding SubPOs}"
ItemContainerStyle="{StaticResource NaviItemContainerStyle}"
ItemTemplate="{StaticResource NaviItemTemplate}"/>
</ScrollViewer>
</GroupBox>
</Grid>
LoginPageViewModel.cs
public class LoginPageViewModel:ViewModelBase
{
private LoginWrapper _login;
private IMessageDialogService _messageDialogService;
public LoginPageViewModel(IMessageDialogService messageDialogService)
{
_messageDialogService = messageDialogService;
}
public LoginWrapper Login
{
get { return _login; }
private set
{
_login = value;
OnPropertyChanged();
}
}
}
LoginWrapper.cs
public class LoginWrapper : ModelWrapper<Login>
{
public LoginWrapper(Login model) : base(model)
{
}
public int Id { get { return Model.Id; } }
public string Email
{
get { return GetValue<string>(); }
set { SetValue(value); }
}
public string Password
{
get { return GetValue<string>(); }
set { SetValue(value); }
}
}
App.xaml.cs
private void Application_Startup(object sender, StartupEventArgs e)
{
var bootstrapper = new Bootstrapper();
var container = bootstrapper.Bootstrap();
var mainWindow = container.Resolve<MainWindow>();
mainWindow.Show();
}
Note: in the Bootstrapper there is a container that contains the whole models and the views For Example:
public class Bootstrapper
{
public IContainer Bootstrap()
{
var builder = new ContainerBuilder();
builder.RegisterType<EventAggregator>().As<IEventAggregator>().SingleInstance();
builder.RegisterType<SubBVDbContext>().AsSelf();
builder.RegisterType<MainWindow>().AsSelf();
builder.RegisterType<SubPODetailViewModel>().As<ISubPODetailViewModel>();
builder.RegisterType<LoginPageViewModel>.AsSelf();
MainWindow.xaml
<Window.Resources>
<DataTemplate DataType="{x:Type viewModel:SubDetailViewModel}">
<view:SubDetailView/>
</DataTemplate>
<DataTemplate DataType="{x:Type viewModel:SubPODetailViewModel}">
<view:SubPODetailView/>
</DataTemplate>
<DataTemplate DataType="{x:Type viewModel:LoginPageViewModel}">
<view:LoginDetailView/>
</DataTemplate>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Menu Grid.ColumnSpan="2" FontSize="13">
<MenuItem Header="Create">
<MenuItem Header="New Subcontractor" Command="{Binding CreateNewDetailCommand}"
CommandParameter="{x:Type viewModel:SubDetailViewModel}"/>
<MenuItem Header="New P.O." Command="{Binding CreateNewDetailCommand}"
CommandParameter="{x:Type viewModel:SubPODetailViewModel}"/>
</MenuItem>
</Menu>
<view:NavigationView Grid.Row="1" DataContext="{Binding NavigationViewModel}"/>
<ContentControl Grid.Row="1" Grid.Column="1" Content="{Binding DetailViewModel}"/>
</Grid>
The Model view 1,The Model view 2
The SolutionExplorer Folders
The Link for My WPF App: http://www.filefactory.com/file/4of3jrkspmog/SubBvApp.zip

WPF ItemControl slow rendering

Hi there I have a WPF application with an image where the user selects an area, once the area is selected a grid with crosses appears over the selected area. I apply some transformations back and forth in order to scale and rotate the grid to match the image coordinates.This is working so far, but when there is a lot of crosses (~+5k) the UI freezes and takes ages to render the crosses. I have applied some answers I found over Stackoverflow, like virtualization, ListView, ListBox, but I cannot make it work. I am wondering if someone can put some light here, thanks in advance!.EDITSo I end up doing all the related calculation to translate the crosses on the ViewModel, in order to do this and not break the MVVM pattern, I use AttachedProperties which gives me on the ViewModel the data needed for the calculation of the positions. Here is the link and the explanation -> https://stackoverflow.com/a/3667609/2315752 Here is the main code:MainWindow.ItemControl:
<ItemsControl ItemsSource="{Binding Crosses}">
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="Canvas.Left"
Value="{Binding X}" />
<Setter Property="Canvas.Top"
Value="{Binding Y}" />
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Path Width="5"
Height="5"
StrokeThickness="1"
Stroke="1"
Style="{StaticResource ShapeCross}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
The key is to layout the item containers on the Canvas and not the items. This way the rendering occurs during the panel's arrange layout pass. Translating the item elements (the content of the item containers) after the containers have been rendered adds additional render time.
Instead of translating the points across the Canvas you should use the attached properties Canvas.Left and Canvas.Top to layout the item containers on the Canvas panel.
The graph manipulation like scaling should be done in the view model directly on the set of data items. To allow dynamic UI updates consider to implement a custom data model which implements INotifyPropertyChanged e.g. ObservablePoint.
The following example draws a sine graph of crosses. The graph consists of 10,800 data points. Load up time is approximately less than 5 seconds, which are spent to create the 10,800 Point instances.
The result is instant rendering and pretty smooth scrolling:
ViewModel.cs
class ViewModel
{
public ObservableCollection<Point> Points { get; set; }
public ViewModel()
{
this.Points = new ObservableCollection<Point>();
// Generate a sine graph of 10,800 points
// with an amplitude of 200px and a vertical offset of 200px
for (int x = 0; x < 360 * 30; x++)
{
var point = new Point()
{
X = x,
Y = Math.Sin(x * Math.PI / 180) * 200 + 200};
}
this.Points.Add(point);
}
}
}
MainWindow.xaml
<Window>
<Window.DataContext>
<ViewModel />
</Window.DataContext>
<ListBox ItemsSource="{Binding Points}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Width="11000" Height="500" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate DataType="Point">
<Grid>
<Line Stroke="Black" StrokeThickness="2" X1="0" X2="10" Y1="5" Y2="5" />
<Line Stroke="Black" StrokeThickness="2" X1="5" X2="5" Y1="0" Y2="10" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Canvas.Left" Value="{Binding X}" />
<Setter Property="Canvas.Top" Value="{Binding Y}" />
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
</Window>
You can make a class that calculates the scale and passes it to the ViewModel.
An approximate implementation and its use.You can make a class that calculates the scale and passes it to the ViewModel.
An approximate implementation and its use.
public class ScaleCalcBinding : Freezable
{
public FrameworkElement SourceElement
{
get { return (FrameworkElement)GetValue(SourceElementProperty); }
set { SetValue(SourceElementProperty, value); }
}
// Using a DependencyProperty as the backing store for SourceElement. This enables animation, styling, binding, etc...
public static readonly DependencyProperty SourceElementProperty =
DependencyProperty.Register(nameof(SourceElement), typeof(FrameworkElement), typeof(ScaleCalcBinding), new PropertyMetadata(null, ElementChanged));
private static void ElementChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
ScaleCalcBinding dd = (ScaleCalcBinding)d;
FrameworkElement element = e.OldValue as FrameworkElement;
if (element != null)
element.SizeChanged -= dd.CalcScale;
element = e.NewValue as FrameworkElement;
if (element != null)
element.SizeChanged += dd.CalcScale;
dd.CalcScale();
}
private void CalcScale(object sender = null, SizeChangedEventArgs e = null)
{
if (SourceElement == null || TargetElement == null || ScanScale == null)
{
ScaleWidthResult = null;
ScaleHeightResult = null;
return;
}
ScaleWidthResult = SourceElement.ActualWidth / TargetElement.ActualWidth * ScanScale.Value;
ScaleHeightResult = SourceElement.ActualHeight / TargetElement.ActualHeight * ScanScale.Value;
}
public FrameworkElement TargetElement
{
get { return (FrameworkElement)GetValue(TargetElementProperty); }
set { SetValue(TargetElementProperty, value); }
}
// Using a DependencyProperty as the backing store for TargetElement. This enables animation, styling, binding, etc...
public static readonly DependencyProperty TargetElementProperty =
DependencyProperty.Register(nameof(TargetElement), typeof(FrameworkElement), typeof(ScaleCalcBinding), new PropertyMetadata(null));
public double? ScanScale
{
get { return (double?)GetValue(ScanScaleProperty); }
set { SetValue(ScanScaleProperty, value); }
}
// Using a DependencyProperty as the backing store for ScanScale. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ScanScaleProperty =
DependencyProperty.Register(nameof(ScanScale), typeof(double?), typeof(ScaleCalcBinding), new PropertyMetadata(null, ElementChanged));
public double? ScaleWidthResult
{
get { return (double?)GetValue(ScaleResultWidthProperty); }
set { SetValue(ScaleResultWidthProperty, value); }
}
// Using a DependencyProperty as the backing store for ScaleWidthResult. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ScaleResultWidthProperty =
DependencyProperty.Register(nameof(ScaleWidthResult), typeof(double?), typeof(ScaleCalcBinding), new PropertyMetadata(null));
public double? ScaleHeightResult
{
get { return (double?)GetValue(ScaleHeightResultProperty); }
set { SetValue(ScaleHeightResultProperty, value); }
}
// Using a DependencyProperty as the backing store for ScaleHeightResult. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ScaleHeightResultProperty =
DependencyProperty.Register(nameof(ScaleHeightResult), typeof(double?), typeof(ScaleCalcBinding), new PropertyMetadata(null));
protected override Freezable CreateInstanceCore() => new ScaleCalcBinding();
}
XAML
<Window
x:Name="window"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:CF2002"
x:Class="CF2002.MainWindow"
Title="MainWindow"
mc:Ignorable="d"
WindowStartupLocation="CenterScreen"
Foreground="White"
Background="#FF79C2FF"
Height="300" Width="300"
FontSize="14">
<Window.Resources>
<local:ViewModelScale x:Key="viewModel"/>
<local:ScaleCalcBinding
x:Key="ScaleCalc"
ScaleHeightResult="{Binding ScaleHeight, Mode=OneWayToSource}"
ScaleWidthResult="{Binding ScaleWidth, Mode=OneWayToSource}"
ScanScale="{Binding Text, ElementName=textBox}"
SourceElement="{Binding ElementName=grid, Mode=OneWay}"
TargetElement="{Binding ElementName=border, Mode=OneWay}"
/>
</Window.Resources>
<Window.DataContext>
<Binding Mode="OneWay" Source="{StaticResource viewModel}"/>
</Window.DataContext>
<Grid x:Name="grid">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock HorizontalAlignment="Left" />
<TextBlock HorizontalAlignment="Right" />
<TextBox x:Name="textBox" TextAlignment="Center"
Background="Transparent"
Text="5"/>
<Grid Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Border x:Name="border" Background="LightGreen">
<StackPanel>
<TextBlock >
<Run Text="{Binding ActualWidth, ElementName=grid, Mode=OneWay}"/>
<Run Text=", "/>
<Run Text="{Binding ActualHeight, ElementName=grid, Mode=OneWay}"/>
</TextBlock>
<TextBlock >
<Run Text="{Binding ActualWidth, ElementName=border, Mode=OneWay}"/>
<Run Text=", "/>
<Run Text="{Binding ActualHeight, ElementName=border, Mode=OneWay}"/>
</TextBlock>
<TextBlock >
<Run Text="{Binding ScaleWidth}"/>
<Run Text=", "/>
<Run Text="{Binding ScaleHeight}"/>
</TextBlock>
</StackPanel>
</Border>
<GridSplitter Grid.Column="1" ShowsPreview="False" Width="3" Grid.RowSpan="3"
HorizontalAlignment="Center" VerticalAlignment="Stretch" />
<GridSplitter Grid.Row="1" ShowsPreview="False" Height="3" Grid.ColumnSpan="3"
VerticalAlignment="Center" HorizontalAlignment="Stretch" Tag="{Binding Mode=OneWay, Source={StaticResource ScaleCalc}}"/>
</Grid>
</Grid>
</Window>
ViewModel
public class ViewModelScale
{
private double _scaleWidth;
private double _scaleHeight;
// In property setters, recalculate coordinate values ​​from the source collection to the collection for display.
public double ScaleWidth { get => _scaleWidth; set { _scaleWidth = value; RenderScale(); } }
public double ScaleHeight { get => _scaleHeight; set { _scaleHeight = value; RenderScale(); } }
public ObservableCollection<CustomType> ViewCollection { get; } = new ObservableCollection<CustomType>();
public ObservableCollection<CustomType> SourceCollection { get; } = new ObservableCollection<CustomType>();
private void RenderScale()
{
for (int i = 0; i < ViewCollection.Count; i++)
{
ViewCollection[i].X = SourceCollection[i].X * ScaleWidth;
ViewCollection[i].Y = SourceCollection[i].Y * ScaleHeight;
}
}
}

Is there are way to manipulate with grid inside StackPanel

I want to create ListBox and inside it should contained some elements.
My code:
<ListBox Name="listBoxQuestion" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ItemsSource="{Binding Path=Tweets}" Background="Gray">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
In which way I cant put in ListBox my Grid and work on it ( I want have opportunity to transform it to star for example)
I have already tried:
<Grid Name="star1" MouseDown="close" Height="50" Width="50" RenderTransformOrigin="0.5,0" Grid.Column="0" Margin="20,0,0,0">
<DataGrid VerticalAlignment="Top" AutoGenerateColumns="False" ItemsSource="{Binding ElementName=listBox, Path=SelectedItem}"/>
</Grid>
XAML:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="800" Width="800" Background="#FF143761">
<Grid Width="600" Margin="114,126,78,335">
<ListBox Name="listBoxQuestion" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ItemsSource="{Binding ITEMS}">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="IsSelected" Value="{Binding Content.IsSelected, Mode=TwoWay, RelativeSource={RelativeSource Self}}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<ContentPresenter/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Width="{Binding WIDTH}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Row="0" Orientation="Horizontal">
<Label Name="id"
Content="{Binding SURVEY_ID}"
Grid.Row="0"
Grid.Column="0"/>
<Label Name="question"
Content="{Binding SURVEY_QUESTION}"
Grid.Row="0"
Grid.Column="1" VerticalAlignment="Stretch" />
</StackPanel>
<StackPanel Grid.Row="2" Orientation="Horizontal">
<Polygon Name="star1" Points="{Binding POINTS}" Fill="{Binding FILL_COLOR}" Stroke="{Binding STROKE_COLOR}" Width="{Binding STAR_WIDTH}" Height="{Binding STAR_HEIGHT}" HorizontalAlignment="{Binding H_Alignment}" VerticalAlignment="{Binding V_Alignment}" MouseDown="clicked"/>
<Polygon Name="star2" Points="{Binding POINTS}" Fill="{Binding FILL_COLOR}" Stroke="{Binding STROKE_COLOR}" Width="{Binding STAR_WIDTH}" Height="{Binding STAR_HEIGHT}" HorizontalAlignment="{Binding H_Alignment}" VerticalAlignment="{Binding V_Alignment}" MouseDown="clicked"/>
<Polygon Name="star3" Points="{Binding POINTS}" Fill="{Binding FILL_COLOR}" Stroke="{Binding STROKE_COLOR}" Width="{Binding STAR_WIDTH}" Height="{Binding STAR_HEIGHT}" HorizontalAlignment="{Binding H_Alignment}" VerticalAlignment="{Binding V_Alignment}" MouseDown="clicked"/>
<Polygon Name="star4" Points="{Binding POINTS}" Fill="{Binding FILL_COLOR}" Stroke="{Binding STROKE_COLOR}" Width="{Binding STAR_WIDTH}" Height="{Binding STAR_HEIGHT}" HorizontalAlignment="{Binding H_Alignment}" VerticalAlignment="{Binding V_Alignment}" MouseDown="clicked"/>
<Polygon Name="star5" Points="{Binding POINTS}" Fill="{Binding FILL_COLOR}" Stroke="{Binding STROKE_COLOR}" Width="{Binding STAR_WIDTH}" Height="{Binding STAR_HEIGHT}" HorizontalAlignment="{Binding H_Alignment}" VerticalAlignment="{Binding V_Alignment}" MouseDown="clicked"/>
</StackPanel>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Window>
CODE:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Drawing;
using System.Collections.ObjectModel;
using System.Text.RegularExpressions;
namespace WpfApplication1
{
public class Item
{
public uint width;
public uint starWidth;
public uint starHeight;
public string id;
public string question;
public PointCollection points;
public SolidColorBrush fillColor;
public SolidColorBrush strokeColor;
public HorizontalAlignment horizontalAlignment;
public VerticalAlignment verticalAlignment;
public uint WIDTH
{
get { return width; }
set { width = value; }
}
public uint STAR_WIDTH
{
get { return starWidth; }
set { starWidth = value; }
}
public uint STAR_HEIGHT
{
get { return starHeight; }
set { starHeight = value; }
}
public string SURVEY_ID
{
get { return id; }
set { id = value; }
}
public string SURVEY_QUESTION
{
get { return question; }
set { question = value; }
}
public PointCollection POINTS
{
get { return points; }
set { points = value; }
}
public SolidColorBrush FILL_COLOR
{
get { return fillColor; }
set { fillColor = value; }
}
public SolidColorBrush STROKE_COLOR
{
get { return strokeColor; }
set { strokeColor = value; }
}
public HorizontalAlignment H_Alignment
{
get { return horizontalAlignment; }
set { horizontalAlignment = value; }
}
public VerticalAlignment V_Alignment
{
get { return verticalAlignment; }
set { verticalAlignment = value; }
}
}
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
listBoxQuestion.ItemsSource = createItems();
}
private List<Item> createItems()
{
List<Item> items = new List<Item>();
items.Add(createItem("1)", "Question 1"));
items.Add(createItem("2)", "Question 2"));
items.Add(createItem("3)", "Question 3"));
return items;
}
private Item createItem(string id, string question)
{
Item item = new Item();
item.width = 800;
item.starHeight = 50;
item.starWidth = 50;
item.horizontalAlignment = HorizontalAlignment.Left;
item.verticalAlignment = VerticalAlignment.Center;
item.id = id;
item.question = question;
item.points = getPoints();
item.fillColor = getFillColor("Transparent");
item.strokeColor = getStrokeColor("Green");
return item;
}
private PointCollection getPoints()
{
PointCollection myPointLeftCollection = new PointCollection();
System.Drawing.PointF[] pts = new System.Drawing.PointF[5];
double rx = 24 / 2;
double ry = 24 / 2;
double cx = 0 + rx;
double cy = 0 + ry;
// Start at the top.
double theta = -Math.PI / 2;
double dtheta = 4 * Math.PI / 5;
for (int i = 0; i < 5; i++)
{
pts[i] = new System.Drawing.PointF(
(float)(cx + rx * Math.Cos(theta)),
(float)(cy + ry * Math.Sin(theta)));
theta += dtheta;
}
System.Windows.Point Point1Feedback = new System.Windows.Point(pts[0].X, pts[0].Y);
System.Windows.Point Point2Feedback = new System.Windows.Point(16, 8);
System.Windows.Point Point3Feedback = new System.Windows.Point(pts[3].X, pts[3].Y);
System.Windows.Point Point4Feedback = new System.Windows.Point(18, 14);
System.Windows.Point Point5Feedback = new System.Windows.Point(pts[1].X, pts[1].Y);
System.Windows.Point Point6Feedback = new System.Windows.Point(12, 18);
System.Windows.Point Point7Feedback = new System.Windows.Point(pts[4].X, pts[4].Y);
System.Windows.Point Point8Feedback = new System.Windows.Point(6, 14);
System.Windows.Point Point9Feedback = new System.Windows.Point(pts[2].X, pts[2].Y);
System.Windows.Point Point10Feedback = new System.Windows.Point(9, 8);
myPointLeftCollection.Add(Point1Feedback);
myPointLeftCollection.Add(Point2Feedback);
myPointLeftCollection.Add(Point3Feedback);
myPointLeftCollection.Add(Point4Feedback);
myPointLeftCollection.Add(Point5Feedback);
myPointLeftCollection.Add(Point6Feedback);
myPointLeftCollection.Add(Point7Feedback);
myPointLeftCollection.Add(Point8Feedback);
myPointLeftCollection.Add(Point9Feedback);
myPointLeftCollection.Add(Point10Feedback);
return myPointLeftCollection;
}
private SolidColorBrush getFillColor(string themeColorInner)
{
return (SolidColorBrush)new BrushConverter().ConvertFromString(themeColorInner);
}
private SolidColorBrush getStrokeColor(string themeColorBorder)
{
return (SolidColorBrush)new BrushConverter().ConvertFromString(themeColorBorder);
}
private void clicked(object sender, RoutedEventArgs e)
{
}
}
}

Clicking listbox usercontrol items in wpf

So in my application I have to types of class objects, Circles and Rectangles. Both which got plotted using a ListBox. The rectangles are green and the circles are the yellow shapes.
You may be asking why am i using the listbox to display them. The benefit here is the freebie of making it possible for users to select the items when the click within the window as seen here.
The problems which i need help on, they all relate to the same topic which is clicking/selection.
Updated: 1/7/2016
Since all listbox items are displayed with a Box Shaped hit test area, it makes problems like this happen. A user wants to select the Rectangle but they get the Yellow Circle instead.
The Problem (Left)| The Desired Goal (Right)
This leads to my last problem which is the hit test for the Yellow Circle shapes. When a user clicks in a negative area it shouldn't actually select the line. It should only select the line when the users cursor is directly over it. as seen in the image on the right. It would be ideal that when it's selected, the highlight indication fits more around the shapes which is highlighted, rather than a huge rectangle.
As far as the code, its rather short, and i combined it for simplicity into lesser files.
MainWindow.xaml
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication1"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525"
Background="Gray">
<Window.DataContext>
<local:MainWindowViewModel />
</Window.DataContext>
<Window.Resources>
<DataTemplate DataType="{x:Type local:RectangleViewModel}" >
<Border Cursor="Hand" Background="Green" CornerRadius="4" Width="100" Height="100" Margin="10"/>
</DataTemplate>
<DataTemplate DataType="{x:Type local:CircleViewModel}" >
<Path Data="M0,0 C0,0 10,100 100,100" Stroke="Gold" StrokeThickness="5" Cursor="Hand"/>
</DataTemplate>
</Window.Resources>
<!-- Presents the Rectangles -->
<ListBox x:Name="listBox" ItemsSource="{Binding Items}" SelectionMode="Extended" Background="Transparent">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem" >
<Setter Property="Canvas.Left" Value="{Binding X}" />
<Setter Property="Canvas.Top" Value="{Binding Y}" />
</Style>
</ListBox.ItemContainerStyle>
<ListBox.Resources>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
</ListBox.Resources>
</ListBox>
</Window>
MainWindowViewModel.cs
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WpfApplication1
{
public class MainWindowViewModel
{
private ObservableCollection<ItemViewModel> items = new ObservableCollection<ItemViewModel>();
public ObservableCollection<ItemViewModel> Items { get { return items; } }
public MainWindowViewModel()
{
// Populate the view model with some example data.
items.Add(new RectangleViewModel(250, 200));
items.Add(new RectangleViewModel(320, 370));
items.Add(new RectangleViewModel(100, 50));
items.Add(new RectangleViewModel(350, 25));
items.Add(new RectangleViewModel(70, 270));
items.Add(new CircleViewModel(20, 20));
items.Add(new CircleViewModel(300, 270));
items.Add(new CircleViewModel(350, 100));
items.Add(new CircleViewModel(50, 315));
items.Add(new CircleViewModel(100, 170));
}
}
public class ItemViewModel
{
// position coordinates
public double X { get; set; }
public double Y { get; set; }
}
public class CircleViewModel : ItemViewModel
{
// Constructors
public CircleViewModel(double x, double y)
{
this.X = x;
this.Y = y;
}
}
public class RectangleViewModel : ItemViewModel
{
// Constructors
public RectangleViewModel(double x, double y)
{
this.X = x;
this.Y = y;
}
}
}
UPDATED - Closer - ATTEMPT #2
Now I have the ability to drag and move items in the canvas with the hitTest of the click being correct. However for some reason when i try to move shapes in the bottom blue canvas they don't move, where as they do move in the top one. Try it out....
MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace DragShapes
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
bool captured = false;
double x_shape, x_canvas, y_shape, y_canvas;
UIElement source = null;
private void shape_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Console.WriteLine("MouseDown--Pressed");
source = (UIElement)sender;
Mouse.Capture(source);
captured = true;
x_shape = Canvas.GetLeft(source);
x_canvas = e.GetPosition(LayoutRoot).X;
y_shape = Canvas.GetTop(source);
y_canvas = e.GetPosition(LayoutRoot).Y;
}
private void shape_MouseMove(object sender, MouseEventArgs e)
{
if (captured)
{
Console.WriteLine("MouseMove--Pressed");
double x = e.GetPosition(LayoutRoot).X;
double y = e.GetPosition(LayoutRoot).Y;
x_shape += x - x_canvas;
Canvas.SetLeft(source, x_shape);
x_canvas = x;
y_shape += y - y_canvas;
Canvas.SetTop(source, y_shape);
y_canvas = y;
}
}
private void
shape_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
Console.WriteLine("MouseUp--Pressed");
Mouse.Capture(null);
captured = false;
}
}
}
MainWindowViewModel.cs
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DragShapes
{
public class MainWindowViewModel
{
private ObservableCollection<ItemViewModel> items = new ObservableCollection<ItemViewModel>();
public ObservableCollection<ItemViewModel> Items { get { return items; } }
public MainWindowViewModel()
{
// Populate the view model with some example data.
items.Add(new RectangleViewModel(250, 200));
items.Add(new RectangleViewModel(320, 370));
items.Add(new RectangleViewModel(100, 50));
items.Add(new RectangleViewModel(350, 25));
items.Add(new RectangleViewModel(70, 270));
items.Add(new CircleViewModel(20, 20));
items.Add(new CircleViewModel(300, 270));
items.Add(new CircleViewModel(350, 100));
items.Add(new CircleViewModel(50, 315));
items.Add(new CircleViewModel(100, 170));
}
}
public class ItemViewModel : INotifyPropertyChanged
{
// position coordinates
private double x = 0;
public double X
{
get { return x; }
set
{
if (x != value)
{
x = value;
OnPropertyChanged("X");
}
}
}
private double y = 0;
public double Y
{
get { return y; }
set
{
if (y != value)
{
y = value;
OnPropertyChanged("Y");
}
}
}
protected void OnPropertyChanged(string name)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
public class CircleViewModel : ItemViewModel
{
// Constructors
public CircleViewModel(double x, double y)
{
this.X = x;
this.Y = y;
}
}
public class RectangleViewModel : ItemViewModel
{
// Constructors
public RectangleViewModel(double x, double y)
{
this.X = x;
this.Y = y;
}
}
}
MainWindow.xaml
<Window x:Class="DragShapes.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="600" Width="600"
xmlns:local="clr-namespace:DragShapes">
<Window.DataContext>
<local:MainWindowViewModel />
</Window.DataContext>
<Window.Resources>
<DataTemplate DataType="{x:Type local:RectangleViewModel}" >
<Rectangle Cursor="Hand" Fill="Green" Width="100" Height="100" Margin="10"
MouseLeftButtonDown="shape_MouseLeftButtonDown"
MouseMove="shape_MouseMove"
MouseLeftButtonUp="shape_MouseLeftButtonUp"/>
</DataTemplate>
<DataTemplate DataType="{x:Type local:CircleViewModel}" >
<Path Data="M0,0 C0,0 10,100 100,100" Stroke="Gold" StrokeThickness="5" Cursor="Hand"
MouseLeftButtonDown="shape_MouseLeftButtonDown"
MouseLeftButtonUp="shape_MouseLeftButtonUp"
MouseMove="shape_MouseMove"/>
</DataTemplate>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Canvas x:Name="LayoutRoot" Background="White">
<Ellipse Fill="Blue" HorizontalAlignment="Center" Height="100" Stroke="Black" VerticalAlignment="Center" Width="100" Canvas.Left="200" Canvas.Top="100"
MouseLeftButtonDown="shape_MouseLeftButtonDown"
MouseMove="shape_MouseMove"
MouseLeftButtonUp="shape_MouseLeftButtonUp" />
<Rectangle Fill="Red" Height="100" Stroke="Black" Width="100" HorizontalAlignment="Left" VerticalAlignment="Bottom" Canvas.Left="10" Canvas.Top="10"
MouseLeftButtonDown="shape_MouseLeftButtonDown"
MouseLeftButtonUp="shape_MouseLeftButtonUp"
MouseMove="shape_MouseMove"/>
</Canvas>
<Canvas Grid.Row="1" Background="White" >
<ItemsControl ItemsSource="{Binding Path=Items}" >
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Background="LightBlue" Width="500" Height="500" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<!--<ItemsControl.ItemTemplate>
<DataTemplate>
<Ellipse Fill="Green" Width="25" Height="25"
MouseLeftButtonDown="shape_MouseLeftButtonDown"
MouseLeftButtonUp="shape_MouseLeftButtonUp"
MouseMove="shape_MouseMove"/>
</DataTemplate>
</ItemsControl.ItemTemplate>-->
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="Canvas.Top" Value="{Binding Path=Y}" />
<Setter Property="Canvas.Left" Value="{Binding Path=X}" />
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
<!--<ItemsControl ItemsSource="{Binding Path=Items}">
<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>-->
<!--<ItemsControl ItemsSource="{Binding Path=Items}">
--><!--<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Left" Value="{Binding X}"/>
<Setter Property="Canvas.Top" Value="{Binding Y}"/>
</Style>
</ItemsControl.ItemContainerStyle>--><!--
</ItemsControl>-->
</Canvas>
</Grid>
</Window>
Default ListBoxItem template has active background, so we need reset the template like this:
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem" >
<Setter Property="Canvas.Left" Value="{Binding X}" />
<Setter Property="Canvas.Top" Value="{Binding Y}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<ContentPresenter/>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="LightBlue"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
Then, we need modify the rectangle and circle templates, to get selection effect, when they are selected:
<DataTemplate DataType="{x:Type local:RectangleViewModel}" >
<Grid>
<Border CornerRadius="4"
Background="{Binding
RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}},
Path=Background}"/>
<Border Cursor="Hand" Background="Green" CornerRadius="4" Width="100" Height="100" Margin="10"/>
</Grid>
</DataTemplate>
<DataTemplate DataType="{x:Type local:CircleViewModel}" >
<Grid>
<Path Data="M0,0 C0,0 10,100 100,100" StrokeThickness="15"
Stroke="{Binding
RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}},
Path=Background}"/>
<Path Data="M0,0 C0,0 10,100 100,100" Stroke="Gold" StrokeThickness="5" Cursor="Hand"/>
</Grid>
</DataTemplate>

WinRT Listview Content becomes invisible after 2^21 pixels?

I have a problem displaying a large dataset (around 27k elements). The problem is that after a certain point items would not display anymore but would still be be clickable. In fact, the items would display when scrolling but would disappear as soon as the scrolling stops. After some testing I found out it was stopping rendering after the 2^21 pixel. Complexity of the objects being rendered do not seem to affect this limit.
I have made a sample project to illustrate this:
In a blank windows store app, replace MainPage.xaml default grid with this one
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="1*"></RowDefinition>
<RowDefinition Height="24"></RowDefinition>
<RowDefinition Height="24"></RowDefinition>
</Grid.RowDefinitions>
<TextBlock x:Name="textblock" Grid.Row="2"></TextBlock>
<Button Grid.Column="0" Grid.Row="1" Tapped="Button_Tapped"></Button>
<Button Grid.Column="1" Grid.Row="1" Tapped="Button_Tapped_1"></Button>
<Button Grid.Column="2" Grid.Row="1" Tapped="Button_Tapped_2"></Button>
<Button Grid.Column="3" Grid.Row="1" Tapped="Button_Tapped_3"></Button>
<ListView Grid.Column="0" Background="Red" x:Name="simpleList1" SelectionChanged="list_SelectionChanged">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Left" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="Margin" Value="0,0,0,-8" />
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate>
<Grid Height="100">
<TextBlock Text="{Binding Index}"></TextBlock>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<ListView Grid.Column="1" Background="DarkGoldenrod" x:Name="simpleList2" SelectionChanged="list_SelectionChanged">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Left" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="Margin" Value="0,0,0,-8" />
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate>
<Grid Height="250">
<TextBlock Text="{Binding Index}"></TextBlock>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<ListView Grid.Column="2" Background="Blue" x:Name="complexList1" SelectionChanged="list_SelectionChanged">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Left" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="Margin" Value="0,0,0,-8" />
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate>
<Grid Height="333">
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="{Binding SimpleItem.Index}"></TextBlock>
<TextBlock Grid.Row="1" Text="{Binding ShortMsg}"></TextBlock>
<TextBlock Grid.Row="2" Text="{Binding RandomNumber}"></TextBlock>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<ListView Grid.Column="3" Background="Violet" x:Name="complexList2" SelectionChanged="list_SelectionChanged">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Left" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="Margin" Value="0,0,0,-8" />
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate>
<Grid Height="500">
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="{Binding SimpleItem.Index}"></TextBlock>
<TextBlock Grid.Row="1" Text="{Binding ShortMsg}"></TextBlock>
<TextBlock Grid.Row="2" Text="{Binding RandomNumber}"></TextBlock>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
And in the MainPage.xaml.cs
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{
public class SimpleItem
{
public int Index { get; set; }
public SimpleItem(int index)
{
Index = index;
}
public override string ToString()
{
return "I am a simple item with index " + Index;
}
}
public class ComplexItem
{
static Random rand = new Random();
public SimpleItem SimpleItem { get; set; }
public string ShortMsg { get; set; }
public double RandomNumber { get; set; }
public ComplexItem(int index)
{
SimpleItem = new SimpleItem(index);
ShortMsg = "My simple item has index " + SimpleItem.Index;
RandomNumber = rand.NextDouble() * (double)SimpleItem.Index;
}
public override string ToString()
{
return "I am a complex item with index " + SimpleItem.Index;
}
}
public ObservableCollection<SimpleItem> listSI = new ObservableCollection<SimpleItem>();
public ObservableCollection<ComplexItem> listCI = new ObservableCollection<ComplexItem>();
public MainPage()
{
this.InitializeComponent();
this.NavigationCacheMode = NavigationCacheMode.Required;
InitializeLists();
simpleList1.ItemsSource = listSI;
simpleList2.ItemsSource = listSI;
complexList1.ItemsSource = listCI;
complexList2.ItemsSource = listCI;
}
private void InitializeLists()
{
for (int i = 0; i < 2000000; ++i)
{
listSI.Add(new SimpleItem(i));
listCI.Add(new ComplexItem(i));
}
}
private void Button_Tapped(object sender, TappedRoutedEventArgs e)
{
int target = (int)Math.Pow(2, 21);
int heigthPerItem = 100;
SimpleItem item = listSI[target / heigthPerItem];
simpleList1.ScrollIntoView(item);
}
private void Button_Tapped_1(object sender, TappedRoutedEventArgs e)
{
int target = (int)Math.Pow(2, 21);
int heigthPerItem = 250;
SimpleItem item = listSI[target / heigthPerItem];
simpleList2.ScrollIntoView(item);
}
private void Button_Tapped_2(object sender, TappedRoutedEventArgs e)
{
int target = (int)Math.Pow(2, 21);
int heigthPerItem = 333;
ComplexItem item = listCI[target / heigthPerItem];
complexList1.ScrollIntoView(item);
}
private void Button_Tapped_3(object sender, TappedRoutedEventArgs e)
{
int target = (int)Math.Pow(2, 21);
int heigthPerItem = 500;
ComplexItem item = listCI[target / heigthPerItem];
complexList2.ScrollIntoView(item);
}
private void list_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (e.AddedItems.Count > 0)
{
string text = e.AddedItems[0].ToString();
textblock.Text = text;
}
}
}
This should be the result (with some info how to use it) : ListViewBugInterface
This person had the same problem as me and says it fixed it by using a VirtualizingStackPanel, but this shouldn't be needed since windows 8.1.
I doubt it is a UI virtualization problem since the ListViews scroll smoothly, the items start appearing when scrolling and can be tapped/clicked.
Anyone had this behavior? Am I missing the obvious? (e.g: to not have a dataset of 27k items) Anyone knows a solution to make the items render after the 2^21 pixel?
TLDR:
When displaying pixels after 2^21 pixels of combined ListViewItem they stop being rendered but can still be clicked. How do I fix this?

Categories

Resources