Silverlight Grid Resize as per mouse move - silverlight

I want to resize the silverlight grid by mouse, in the similar way we resize the window using mouse.
I implemented the mouse move event in order to perform the needed task, but its allows the proper resizing from top, left & top left edge of the grid only, not from other size.
Here is the code, I implemented:
XAML Code (UI)
<Border Grid.Column="0" x:Name="LayoutRoot" BorderBrush="Transparent" Padding="0" CornerRadius="3" BorderThickness="0" >
<Border.Background>
<SolidColorBrush x:Name="LayoutBackground" Color="WhiteSmoke" Opacity=".5" />
</Border.Background>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Border Grid.Column="0" x:Name="Layout_TopLeftEdge" Opacity=".0" Cursor="SizeNWSE" CornerRadius="5" Height="5" Width="5" Background="LightGray" VerticalAlignment="Top" HorizontalAlignment="Left"
MouseLeftButtonDown="LayoutGrid_MouseLeftButtonDown" MouseLeftButtonUp="LayoutGrid_MouseLeftButtonUp" MouseMove="LayoutGrid_MouseMove">
<TextBlock x:Name="TopLeftEdge">.</TextBlock>
</Border>
<Border Grid.Column="1" x:Name="Layout_TopEdge" Opacity=".0" Cursor="SizeNS" CornerRadius="5" Height="5" Background="LightGray"
MouseLeftButtonDown="LayoutGrid_MouseLeftButtonDown" MouseLeftButtonUp="LayoutGrid_MouseLeftButtonUp" MouseMove="LayoutGrid_MouseMove">
<TextBlock x:Name="TopEdge">.</TextBlock>
</Border>
<Border Grid.Column="2" x:Name="Layout_TopRightEdge" Opacity=".0" Cursor="SizeNESW" CornerRadius="5" Height="5" Width="5" Background="LightGray" VerticalAlignment="Top" HorizontalAlignment="Right"
MouseLeftButtonDown="LayoutGrid_MouseLeftButtonDown" MouseLeftButtonUp="LayoutGrid_MouseLeftButtonUp" MouseMove="LayoutGrid_MouseMove">
<TextBlock x:Name="TopRightEdge">.</TextBlock>
</Border>
</Grid>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Border Grid.Column="0" x:Name="Layout_LeftEdge" Opacity=".0" Cursor="SizeWE" CornerRadius="5" Width="5" Background="LightGray" VerticalAlignment="Stretch" HorizontalAlignment="Left"
MouseLeftButtonDown="LayoutGrid_MouseLeftButtonDown" MouseLeftButtonUp="LayoutGrid_MouseLeftButtonUp" MouseMove="LayoutGrid_MouseMove">
<TextBlock x:Name="LeftEdge">.</TextBlock>
</Border>
<Border Grid.Column="1" x:Name="LayoutRootBorder" Style="{StaticResource GlassBorderStyle}" MouseLeftButtonDown="LayoutRoot_MouseLeftButtonDown" MouseLeftButtonUp="LayoutRoot_MouseLeftButtonUp" MouseMove="LayoutRoot_MouseMove">
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
<Grid x:Name="LegendGrid" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<!--<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />-->
</Grid.RowDefinitions>
<!--<TextBlock Grid.Row="1" Grid.ColumnSpan="2" Text="Legend" FontStyle="Normal" FontWeight="Bold" Margin="0" TextAlignment="Left" />-->
<!--<tree:TreeViewIcon Grid.Column="0" Style="{StaticResource IconStyle}"
IconType="Circle"
StrokeColor="Red"
StrokeThicknessPercent="20"
FillColor="LightGreen" />
<tree:TreeViewIcon Grid.Column="0" Grid.Row="1" Style="{StaticResource IconStyle}"
IconType="Rectangle"
StrokeColor="Blue"
StrokeThicknessPercent="20"
FillColor="Yellow" />
<TextBlock Grid.Column="1" Grid.Row="1" Text="Layer Name #2" Style="{StaticResource TokenTextStyle}" />-->
</Grid>
</ScrollViewer>
</Border>
<Border Grid.Column="2" x:Name="Layout_RightEdge" Opacity=".0" Cursor="SizeWE" CornerRadius="5" Width="5" Background="LightGray" VerticalAlignment="Stretch" HorizontalAlignment="Right"
MouseLeftButtonDown="LayoutGrid_MouseLeftButtonDown" MouseLeftButtonUp="LayoutGrid_MouseLeftButtonUp" MouseMove="LayoutGrid_MouseMove">
<TextBlock x:Name="RightEdge">.</TextBlock>
</Border>
</Grid>
<Grid Grid.Row="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Border Grid.Column="0" x:Name="Layout_BottomLeftEdge" Opacity=".0" Cursor="SizeNESW" CornerRadius="5" Height="5" Width="5" Background="LightGray" VerticalAlignment="Bottom" HorizontalAlignment="Left"
MouseLeftButtonDown="LayoutGrid_MouseLeftButtonDown" MouseLeftButtonUp="LayoutGrid_MouseLeftButtonUp" MouseMove="LayoutGrid_MouseMove">
<TextBlock x:Name="BottomLeftEdge">.</TextBlock>
</Border>
<Border Grid.Column="1" x:Name="Layout_BottomEdge" Opacity=".0" Cursor="SizeNS" CornerRadius="5" Height="5" Background="LightGray"
MouseLeftButtonDown="LayoutGrid_MouseLeftButtonDown" MouseLeftButtonUp="LayoutGrid_MouseLeftButtonUp" MouseMove="LayoutGrid_MouseMove">
<TextBlock x:Name="BottomEdge">.</TextBlock>
</Border>
<Border Grid.Column="2" x:Name="Layout_BottomRightEdge" Opacity=".0" Cursor="SizeNWSE" CornerRadius="5" Height="5" Width="5" Background="LightGray" VerticalAlignment="Bottom" HorizontalAlignment="Right"
MouseLeftButtonDown="LayoutGrid_MouseLeftButtonDown" MouseLeftButtonUp="LayoutGrid_MouseLeftButtonUp" MouseMove="LayoutGrid_MouseMove">
<TextBlock x:Name="BottomRightEdge">.</TextBlock>
</Border>
</Grid>
</Grid>
</Border>
XAML.cs Code (Code-Behind)
bool IsMouseDown_LayoutGrid;
enum cornerEdge { None = 0, TopLeft = 1, TopRight = 2, BottomRight = 3, BottomLeft = 4, Top = 5, Right = 6, Bottom = 7, Left = 8 };
cornerEdge Edge = 0;
Point ResizeOffset;
private void LayoutGrid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
IsMouseDown_LayoutGrid = true;
ResizeOffset = e.GetPosition(OuterGrid);
switch ((e.OriginalSource as TextBlock).Name)
{
case "TopLeftEdge":
Edge = cornerEdge.TopLeft;
Layout_TopLeftEdge.CaptureMouse();
break;
case "TopEdge":
Edge = cornerEdge.Top;
Layout_TopEdge.CaptureMouse();
break;
case "TopRightEdge":
Edge = cornerEdge.TopRight;
Layout_TopRightEdge.CaptureMouse();
break;
case "LeftEdge":
Edge = cornerEdge.Left;
Layout_LeftEdge.CaptureMouse();
break;
case "RightEdge":
Edge = cornerEdge.Right;
Layout_RightEdge.CaptureMouse();
break;
case "BottomLeftEdge":
Edge = cornerEdge.BottomLeft;
Layout_BottomLeftEdge.CaptureMouse();
break;
case "BottomEdge":
Edge = cornerEdge.Bottom;
Layout_BottomEdge.CaptureMouse();
break;
case "BottomRightEdge":
Edge = cornerEdge.BottomRight;
Layout_BottomRightEdge.CaptureMouse();
break;
}
}
private void LayoutGrid_MouseMove(object sender, MouseEventArgs e)
{
if (IsMouseDown_LayoutGrid)
{
// we want to move it based on the position of the mouse
moveGridControl(e);
}
}
private void moveGridControl(MouseEventArgs e)
{
Point mousePos = e.GetPosition(OuterGrid);
Point diff = new Point(ResizeOffset.X - mousePos.X, ResizeOffset.Y - mousePos.Y);
if (double.IsNaN(OuterGrid.Width))
OuterGrid.Width = OuterGrid.MinWidth;
if (double.IsNaN(OuterGrid.Height))
OuterGrid.Height = OuterGrid.MinHeight;
if (Edge == cornerEdge.TopLeft)
{
if ((OuterGrid.Width + diff.X) >= OuterGrid.MinWidth && (OuterGrid.Width + diff.X) <= OuterGrid.MaxWidth)
{
OuterGrid.Width += diff.X;
}
if ((OuterGrid.Height + diff.Y) >= OuterGrid.MinHeight && (OuterGrid.Height + diff.Y) <= OuterGrid.MaxHeight)
{
OuterGrid.Height += diff.Y;
}
}
else if (Edge == cornerEdge.Top)
{
if ((OuterGrid.Height + diff.Y) >= OuterGrid.MinHeight && (OuterGrid.Height + diff.Y) <= OuterGrid.MaxHeight)
{
OuterGrid.Height += diff.Y;
}
}
else if (Edge == cornerEdge.TopRight)
{
//diff.X = -diff.X;
if ((OuterGrid.Width + diff.X) >= OuterGrid.MinWidth && (OuterGrid.Width + diff.X) <= OuterGrid.MaxWidth)
{
OuterGrid.Width += diff.X;
//MainTranslateTransform.X += (diff.X);
}
if ((OuterGrid.Height + diff.Y) >= OuterGrid.MinHeight && (OuterGrid.Height + diff.Y) <= OuterGrid.MaxHeight)
{
OuterGrid.Height += diff.Y;
//MainTranslateTransform.Y += (diff.Y);
}
}
else if (Edge == cornerEdge.Left)
{
if ((OuterGrid.Width + diff.X) >= OuterGrid.MinWidth && (OuterGrid.Width + diff.X) <= OuterGrid.MaxWidth)
{
OuterGrid.Width += diff.X;
}
}
else if (Edge == cornerEdge.Right)
{
//diff.X = -diff.X;
if ((OuterGrid.Width + diff.X) >= OuterGrid.MinWidth && (OuterGrid.Width + diff.X) <= OuterGrid.MaxWidth)
{
OuterGrid.Width += diff.X;
}
}
else if (Edge == cornerEdge.BottomLeft)
{
if ((OuterGrid.Width + diff.X) >= OuterGrid.MinWidth && (OuterGrid.Width + diff.X) <= OuterGrid.MaxWidth)
{
OuterGrid.Width += diff.X;
}
//diff.Y = -diff.Y;
if ((OuterGrid.Height + diff.Y) >= OuterGrid.MinHeight && (OuterGrid.Height + diff.Y) <= OuterGrid.MaxHeight)
{
OuterGrid.Height += diff.Y;
}
}
else if (Edge == cornerEdge.Bottom)
{
//diff.Y = -diff.Y;
if ((OuterGrid.Height + diff.Y) >= OuterGrid.MinHeight && (OuterGrid.Height + diff.Y) <= OuterGrid.MaxHeight)
{
OuterGrid.Height += diff.Y;
}
}
else if (Edge == cornerEdge.BottomRight)
{
if ((OuterGrid.Width + diff.X) >= OuterGrid.MinWidth && (OuterGrid.Width + diff.X) <= OuterGrid.MaxWidth)
{
OuterGrid.Width += diff.X;
}
//diff.Y = -diff.Y;
if ((OuterGrid.Height + diff.Y) >= OuterGrid.MinHeight && (OuterGrid.Height + diff.Y) <= OuterGrid.MaxHeight)
{
OuterGrid.Height += diff.Y;
}
}
}
private void LayoutGrid_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
IsMouseDown_LayoutGrid = false;
switch (Edge)
{
case cornerEdge.TopLeft:
Layout_TopLeftEdge.ReleaseMouseCapture();
break;
case cornerEdge.Top:
Layout_TopEdge.ReleaseMouseCapture();
break;
case cornerEdge.TopRight:
Layout_TopRightEdge.ReleaseMouseCapture();
break;
case cornerEdge.Left:
Layout_LeftEdge.ReleaseMouseCapture();
break;
case cornerEdge.Right:
Layout_RightEdge.ReleaseMouseCapture();
break;
case cornerEdge.BottomLeft:
Layout_BottomLeftEdge.ReleaseMouseCapture();
break;
case cornerEdge.Bottom:
Layout_BottomEdge.ReleaseMouseCapture();
break;
case cornerEdge.BottomRight:
Layout_BottomRightEdge.ReleaseMouseCapture();
break;
}
Edge = 0;
}

Related

Can't left click on TextBox in a ListBox (With drag and drop) WPF

I have a ListBox that contains a TextBox (And also picture and other thing).
The problem is I can't left click in the TextBox because of the previewmouseleftbuttondown which i handle for the ListBox.
It means that the program handle my left click with this function and thats why I can't write in the textBox.
What can i do about it?
The listBox:
ListBox x:Name="lbTwo" Grid.Column="2 " Margin="{StaticResource SplitRight}"
Drop="ListBox_Drop" AllowDrop="True"
PreviewMouseLeftButtonDown="ListBox_PreviewMouseLeftButtonDown" MouseDown="someListBox_MouseDown"
Style="{DynamicResource ResourceKey=styleLightListBox}"
ScrollViewer.VerticalScrollBarVisibility="Visible">
The items it contains:
<DataTemplate x:Key="templateLightListBoxItem">
<Grid Margin="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Border Grid.Column="0"
Grid.Row="0"
Grid.RowSpan="2"
Margin="0,0,10,0">
<Image Source="{Binding Path=Number_pic}"
Stretch="Fill"
Height="40"
Width="40"></Image>
</Border>
<TextBlock Text="{Binding Path=Name}"
FontWeight="Bold"
Grid.Column="1"
Grid.Row="0"></TextBlock>
<Grid
Grid.Column="1"
Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Label x:Name="label" Content="Your number: " Grid.Column="0" />
<TextBox x:Name="NumberTextBox" PreviewTextInput="NumberValidationTextBox" Text="{Binding Path=mainNumber, UpdateSourceTrigger=PropertyChanged}" Grid.Column="1" Width="20"/>
</Grid>
</Grid>
</DataTemplate>
Edit:
private void ListBox_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
ListBox destLisBox = (ListBox)sender;
dragSource = destLisBox;
GiveFeedbackEventHandler handler = new GiveFeedbackEventHandler(DragSource_GiveFeedback);
this.dragSource.GiveFeedback += handler;
object data = GetDataFromListBox(dragSource, e.GetPosition(destLisBox));
if (data != null)
{
DragDrop.DoDragDrop(destLisBox, data, DragDropEffects.Move);
}
}
private void DragSource_GiveFeedback(object sender, GiveFeedbackEventArgs e)
{
try
{
//This loads the cursor from a stream ..
if (_allOpsCursor == null)
{
{
_allOpsCursor = new Cursor(path+#"\Icons\Red_Gear.cur");
}
}
Mouse.SetCursor(_allOpsCursor);
e.UseDefaultCursors = false;
e.Handled = true;
}
finally { }
}

Button width not set to the assigned value

I am implementing a Grid of button with 3 columns one shown and other 2 are collapsed to start with.
Have set the Grid width to be Auto
Set the shown button size to BUTTONWIDTH = 50
Set the collapsed buttons size to EXTNBUTTONWIDTH = 20
I show the Collapsed buttons only button click event of the first button. I see that neither button sizes are honored the width size I have specified. when I look at the width of the button in debugger, width and maxwidth is 50 but actualwidth is 98. However the height of the buttons are displayed as I have set.
I have attached the code, please have a look and give me your suggestion on how to fix the issue.
for (int leftCol = 0; leftCol < 3; leftCol++)
{
this.leftButtonGrid.ColumnDefinitions.Add(new ColumnDefinition() { Width = GridLength.Auto });
for (int leftRow = 0; leftRow < CHARTDOMLEN; leftRow++)
{
this.leftButtonGrid.RowDefinitions.Add(new RowDefinition() { Height = GridLength.Auto });
Button btnOrderSell = new Button();
btnOrderSell.HorizontalContentAlignment = HorizontalAlignment.Left;
btnOrderSell.Height = BUTTONHEIGHT;
btnOrderSell.BorderBrush = Brushes.Black;
// To avoid double borderline
if (leftRow > 0)
btnOrderSell.BorderThickness = new Thickness() { Top = 0, Bottom = 1, Left = 1, Right = 1 };
btnOrderSell.Click += Button_Click;
if (leftCol == 0)
{
btnOrderSell.MaxWidth = BUTTONWIDTH;
btnOrderSell.Width = BUTTONWIDTH;
this.TL0[leftRow] = btnOrderSell;
}
else
{
btnOrderSell.MaxWidth = EXTNBUTTONWIDTH;
btnOrderSell.Width = EXTNBUTTONWIDTH;
btnOrderSell.Visibility = Visibility.Collapsed;
if (leftCol == 1)
{
this.TL1[leftRow] = btnOrderSell;
}
else
this.TL2[leftRow] = btnOrderSell;
}
Grid.SetColumn(btnOrderSell, leftCol);
Grid.SetRow(btnOrderSell, leftRow);
this.leftButtonGrid.Children.Add(btnOrderSell);
}
}
XAML code
<Grid x:Name="OrderBuyGridButtons">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="30" />
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="15"/>
<RowDefinition Height="24"/>
<RowDefinition Height="24"/>
<RowDefinition Height="24"/>
</Grid.RowDefinitions>
<!--<Button x:Name="btn00" Grid.Column="0" Grid.Row="0" Width="30" Visibility="Collapsed" />-->
<Button x:Name="btn00" Grid.Column="0" Grid.Row="1" Width="30" Visibility="Collapsed"/>
<Button Grid.Column="0" Grid.Row="2" Width="30" Visibility="Collapsed" />
<Button Grid.Column="0" Grid.Row="3" Width="30" Visibility="Collapsed" />
<!--<Button x:Name="btn01" Grid.Column="1" Grid.Row="0" Width="30" Visibility="Collapsed" />-->
<Button x:Name="btn01" Grid.Column="1" Grid.Row="1" Width="30" Visibility="Collapsed" />
<Button Grid.Column="1" Grid.Row="2" Width="30" Visibility="Collapsed" />
<Button Grid.Column="1" Grid.Row="3" Width="30" Visibility="Collapsed" />
<!--<Button Grid.Column="2" Grid.Row="0" Width="80" />-->
<Button Grid.Column="2" Grid.Row="1" Width="80" Background="Gainsboro" Click="Button_Click" BorderBrush="Black"/>
<Button Grid.Column="2" Grid.Row="2" Width="80" Background="Gainsboro" BorderBrush="Black"/>
<Button Grid.Column="2" Grid.Row="3" Width="80" Background="Gainsboro" BorderBrush="Black"/>

Massive performance issue with nested ItemsControl

I use a nested ItemsControl to display hierarchical data. Problem is that this is terribly slow even with little data. Its also blocking the UI-Thread completely until data is loaded. What am I doing wrong here?
Code to generate Demo-Data and bind it to the ItemsControl:
private void SetupDemodata()
{
ObservableCollection<Folder> demoData = new ObservableCollection<Folder>();
const int numberOfFolders = 1;
const int numberOfFiles = 1;
const int numberOfLines = 300;
Random randContentLength = new Random();
for( int indexFolders = 0; indexFolders <= numberOfFolders; indexFolders++ )
{
Folder newFolder = new Folder {FolderName = string.Format( "DemoFolder {0}", indexFolders )};
for( int indexFiles = 0; indexFiles <= numberOfFiles; indexFiles++ )
{
File newFile = new File {FileName = string.Format( "DemoFile {0} -> {1}", indexFolders, indexFiles )};
for( int indexLines = 0; indexLines <= numberOfLines; indexLines++ )
{
newFile.ContentLines.Add( new FileContentLine
{
LineContent = GetRandomString( randContentLength.Next( 80 ) ),
LineNumber = indexLines
} );
}
newFolder.Files.Add( newFile );
}
demoData.Add( newFolder );
}
this.icFolders.ItemsSource = demoData;
}
private static readonly Random random = new Random();
private static string GetRandomString(int length )
{
length = Math.Max( length, 3 );
byte[] bytes = new byte[length];
random.NextBytes( bytes );
return Convert.ToBase64String( bytes ).Substring( 0, length );
}
The models:
public class Folder
{
public List<File> Files { get; set; }
public string FolderName { get; set; }
public Folder(){ this.Files = new List<File>();}
}
public class File
{
public List<FileContentLine> ContentLines { get; set; }
public string FileName { get; set; }
public File() { this.ContentLines = new List<FileContentLine>(); }
}
public class FileContentLine
{
public int LineNumber { get; set; }
public string LineContent { get; set; }
}
And the XAML:
<Grid>
<ScrollViewer VerticalScrollBarVisibility="Auto">
<Grid>
<Grid>
<ItemsControl Grid.Row="0" x:Name="icFolders" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" >
<!-- Folder -->
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type local:Folder}">
<Grid Margin="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Border Grid.Row="0" BorderThickness="0,1,0,1" BorderBrush="#c5c5c5">
<Grid Grid.Row="0" Style="{StaticResource styleGridGradient}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Style="{StaticResource styleLabelBold}" Content="{Binding FolderName}" />
<Label Grid.Column="2" Style="{StaticResource styleLabelBold}" Content="{Binding Files.Count}" />
</Grid>
</Grid>
</Border>
<Border Grid.Row="1" BorderThickness="0,1,0,1" BorderBrush="#c5c5c5">
<Grid Style="{StaticResource styleGridGradient}">
<Label Foreground="#666666"
Margin="5,0,0,0"
HorizontalAlignment="Stretch"
Content="{Binding FolderName}" />
</Grid>
</Border>
<!--Files -->
<ItemsControl Grid.Row="2" ItemsSource="{Binding Files}" >
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type local:File}">
<Grid Margin="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Border Grid.Row="0" BorderThickness="0,1,0,1" BorderBrush="#c5c5c5">
<Grid Style="{StaticResource styleGridGradient}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0"
Foreground="#666666"
Margin="5,0,0,0"
VerticalContentAlignment="Center"
VerticalAlignment="Center"
Content="{Binding FileName}" />
<Button Grid.Column="1" Margin="5" MaxHeight="25" Content="Open File"/>
</Grid>
</Border>
<!-- Lines -->
<ItemsControl Grid.Row="1" ItemsSource="{Binding ContentLines}" Background="White">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type local:FileContentLine}">
<Grid Margin="0" Height="20">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="35" />
<ColumnDefinition Width="20" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Border Grid.Column="0" BorderThickness="0,0,1,0" BorderBrush="#c5c5c5">
<ToggleButton>
<Label Content="{Binding LineNumber}" />
</ToggleButton>
</Border>
<Border Grid.Column="2" BorderThickness="0,0,1,0" BorderBrush="#c5c5c5">
<Border Grid.Column="2" BorderThickness="0,1,0,1" BorderBrush="Red">
<Label Height="20" Content="+" HorizontalAlignment="Center" />
</Border>
</Border>
<Border Grid.Column="3" BorderThickness="0,1,0,1" BorderBrush="Gray">
<TextBox Height="20" IsReadOnly="True"
VerticalAlignment="Center"
VerticalContentAlignment="Center"
Text="{Binding LineContent}" />
</Border>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</Grid>
</ScrollViewer>
</Grid>
Add the following property to all your ItemsControls (root and nested ones):
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>

Get Grid Row and Column from X and Y Location

I have a Grid and I know the X-value and Y-Value of where I clicked with my mouse.
Example: X: 235, Y: 235 --> This should be Column: 3 and Row: 3
How Do I get what column and Row is on that x,y coordinate?
Do I really need to add every width of the rows/columns till I get to the required x/y value?
I'm using WPF (for my grid) & c# (for the x & y position)
Can anybody help me with this?
The Math.Floor function, so for example:
Math.Floor(235/scale)
where scale is the the width or height of the grid cell.
Define:
Returns the largest integer less than or equal to the specified number. Math.ceil is the opposite.
For this please do consider ...
You grid has some background color set (even Transparent will do). This is for hit test (mouse click on blank grid area) to work.
GridSplitter itself is a member in the grid. This is important to know because clicking the grid splitter would also show the corresponding cell indices (Column, Row) in which the grid splitter lies.
We are not concerned with ColumnSpan and RowSpan here.
XAML ...
<Window x:Class="WpfApplication3.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid Mouse.PreviewMouseDown="Grid_MouseDown"
Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<GridSplitter ResizeDirection="Rows"
Width="{Binding ActualWidth,
RelativeSource={RelativeSource
AncestorType=Grid}}"
Height="4" Grid.ColumnSpan="3"
Background="Red" Grid.Row="1" />
<TextBox Height="60" AcceptsReturn="True"
Text="Element1"
ScrollViewer.VerticalScrollBarVisibility="Visible" />
<Button Content="Element2" Grid.Column="1"/>
<TextBlock Text="Element4" Grid.Row="2" Width="100"
Height="40" HorizontalAlignment="Left"
VerticalAlignment="Center"/>
<ComboBox SelectedIndex="0" Height="20"
Grid.Column="1" Grid.Row="2">
<ComboBoxItem Content="Element5"/>
</ComboBox>
<CheckBox Content="Element3" Grid.Column="2"/>
<RadioButton Content="Element6" Grid.Row="2"
Grid.Column="2" VerticalAlignment="Center"
HorizontalAlignment="Center"/>
</Grid>
<StackPanel Orientation="Horizontal" Grid.Row="1">
<TextBlock Text="Selected Column and Row is ... " Margin="5"/>
<TextBlock x:Name="StatusTextBlock" FontSize="12"
FontWeight="SemiBold" Margin="5"/>
</StackPanel>
</Grid>
</Window>
Code Behind ..
private void Grid_MouseDown(object sender, MouseButtonEventArgs e)
{
int selectedColumnIndex = -1, selectedRowIndex = -1;
var grid = sender as Grid;
if (grid != null)
{
var pos = e.GetPosition(grid);
var temp = pos.X;
for (var i = 0; i < grid.ColumnDefinitions.Count; i++ )
{
var colDef = grid.ColumnDefinitions[i];
temp -= colDef.ActualWidth;
if (temp <= -1)
{
selectedColumnIndex = i;
break;
}
}
temp = pos.Y;
for (var i = 0; i < grid.RowDefinitions.Count; i++)
{
var rowDef = grid.RowDefinitions[i];
temp -= rowDef.ActualHeight;
if (temp <= -1)
{
selectedRowIndex = i;
break;
}
}
}
StatusTextBlock.Text = selectedColumnIndex + ", " + selectedRowIndex;
}

WPF: Prevent BorderThickness from scaling

I'm rather new at WPF and I need some help.
I have a ViewBox on my for and inside the ViewBox an Ellipse and a Border.
When I resize the form I want the Ellipse and the Border to scale automatically (what it does).
But I don't want the BorderThickness to scale. The thickness of the border should stay 3 pixels.
Does anyone know how to accomplish this?
Here is my XAML:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="StretchTest.MainWindow"
x:Name="Window"
Title="MainWindow"
Width="700" Height="400">
<Grid x:Name="LayoutRoot">
<Viewbox>
<Grid Height="300" Width="400" HorizontalAlignment="Center" VerticalAlignment="Center">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Ellipse Fill="#FF7171EB" Stroke="#FF041374" StrokeThickness="3" Grid.Row="0" Grid.Column="0"/>
<Border BorderBrush="Red" BorderThickness="3" CornerRadius="8" Grid.Row="0" Grid.Column="0"/>
<Ellipse Fill="#FF7171EB" Stroke="#FF041374" StrokeThickness="3" Grid.Row="0" Grid.Column="1"/>
<Border BorderBrush="Red" BorderThickness="3" CornerRadius="8" Grid.Row="0" Grid.Column="1"/>
<Ellipse Fill="#FF7171EB" Stroke="#FF041374" StrokeThickness="3" Grid.Row="0" Grid.Column="2"/>
<Border BorderBrush="Red" BorderThickness="3" CornerRadius="8" Grid.Row="0" Grid.Column="2"/>
<Ellipse Fill="#FF7171EB" Stroke="#FF041374" StrokeThickness="3" Grid.Row="0" Grid.Column="3"/>
<Border BorderBrush="Red" BorderThickness="3" CornerRadius="8" Grid.Row="0" Grid.Column="3"/>
<Ellipse Fill="#FF7171EB" Stroke="#FF041374" StrokeThickness="3" Grid.Row="1" Grid.Column="0"/>
<Border BorderBrush="Red" BorderThickness="3" CornerRadius="8" Grid.Row="1" Grid.Column="0"/>
<Ellipse Fill="#FF7171EB" Stroke="#FF041374" StrokeThickness="3" Grid.Row="1" Grid.Column="1"/>
<Border BorderBrush="Red" BorderThickness="3" CornerRadius="8" Grid.Row="1" Grid.Column="1"/>
<Ellipse Fill="#FF7171EB" Stroke="#FF041374" StrokeThickness="3" Grid.Row="1" Grid.Column="2"/>
<Border BorderBrush="Red" BorderThickness="3" CornerRadius="8" Grid.Row="1" Grid.Column="2"/>
<Ellipse Fill="#FF7171EB" Stroke="#FF041374" StrokeThickness="3" Grid.Row="1" Grid.Column="3"/>
<Border BorderBrush="Red" BorderThickness="3" CornerRadius="8" Grid.Row="1" Grid.Column="3"/>
<Ellipse Fill="#FF7171EB" Stroke="#FF041374" StrokeThickness="3" Grid.Row="2" Grid.Column="0"/>
<Border BorderBrush="Red" BorderThickness="3" CornerRadius="8" Grid.Row="2" Grid.Column="0"/>
<Ellipse Fill="#FF7171EB" Stroke="#FF041374" StrokeThickness="3" Grid.Row="2" Grid.Column="1"/>
<Border BorderBrush="Red" BorderThickness="3" CornerRadius="8" Grid.Row="2" Grid.Column="1"/>
<Ellipse Fill="#FF7171EB" Stroke="#FF041374" StrokeThickness="3" Grid.Row="2" Grid.Column="2"/>
<Border BorderBrush="Red" BorderThickness="3" CornerRadius="8" Grid.Row="2" Grid.Column="2"/>
<Ellipse Fill="#FF7171EB" Stroke="#FF041374" StrokeThickness="3" Grid.Row="2" Grid.Column="3"/>
<Border BorderBrush="Red" BorderThickness="3" CornerRadius="8" Grid.Row="2" Grid.Column="3"/>
</Grid>
</Viewbox>
</Grid>
Thanks for any help!
I would suggest not using a ViewBox. If you don't set the width and height of the ellipse and border, they will size with the window automatically. Instead use a grid to set the relative size of the controls using row height and column width percentages (eg. 0.6*)
Update - Example
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.4*" />
<ColumnDefinition Width="0.6*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Border Grid.Row="1" Name="border1" BorderBrush="Black" BorderThickness="1" Padding="2">
<Ellipse Name="ellipse1" Stroke="Black" Grid.Row="1" Stretch="UniformToFill" />
</Border>
</Grid>
Update
Hmmm, not seeing a easy way to do exactly what you need. Below is the closest I've been able to come.
The only other options I can see:
Put each ellipse in it's own view box
Size the grid columns & rows in code on window resize
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Ellipse Fill="#FF7171EB" Stroke="#FF041374" StrokeThickness="3" Grid.Row="0" Grid.Column="0" Stretch="UniformToFill"/>
<Border BorderBrush="Red" BorderThickness="3" CornerRadius="8" Grid.Row="0" Grid.Column="0"/>
<Ellipse Fill="#FF7171EB" Stroke="#FF041374" StrokeThickness="3" Grid.Row="0" Grid.Column="1" Stretch="UniformToFill"/>
<Border BorderBrush="Red" BorderThickness="3" CornerRadius="8" Grid.Row="0" Grid.Column="1"/>
<Ellipse Fill="#FF7171EB" Stroke="#FF041374" StrokeThickness="3" Grid.Row="0" Grid.Column="2" Stretch="UniformToFill"/>
<Border BorderBrush="Red" BorderThickness="3" CornerRadius="8" Grid.Row="0" Grid.Column="2"/>
<Ellipse Fill="#FF7171EB" Stroke="#FF041374" StrokeThickness="3" Grid.Row="0" Grid.Column="3" Stretch="UniformToFill"/>
<Border BorderBrush="Red" BorderThickness="3" CornerRadius="8" Grid.Row="0" Grid.Column="3"/>
<Ellipse Fill="#FF7171EB" Stroke="#FF041374" StrokeThickness="3" Grid.Row="1" Grid.Column="0" Stretch="UniformToFill"/>
<Border BorderBrush="Red" BorderThickness="3" CornerRadius="8" Grid.Row="1" Grid.Column="0"/>
<Ellipse Fill="#FF7171EB" Stroke="#FF041374" StrokeThickness="3" Grid.Row="1" Grid.Column="1" Stretch="UniformToFill"/>
<Border BorderBrush="Red" BorderThickness="3" CornerRadius="8" Grid.Row="1" Grid.Column="1"/>
<Ellipse Fill="#FF7171EB" Stroke="#FF041374" StrokeThickness="3" Grid.Row="1" Grid.Column="2" Stretch="UniformToFill"/>
<Border BorderBrush="Red" BorderThickness="3" CornerRadius="8" Grid.Row="1" Grid.Column="2"/>
<Ellipse Fill="#FF7171EB" Stroke="#FF041374" StrokeThickness="3" Grid.Row="1" Grid.Column="3" Stretch="UniformToFill"/>
<Border BorderBrush="Red" BorderThickness="3" CornerRadius="8" Grid.Row="1" Grid.Column="3"/>
<Ellipse Fill="#FF7171EB" Stroke="#FF041374" StrokeThickness="3" Grid.Row="2" Grid.Column="0" Stretch="UniformToFill"/>
<Border BorderBrush="Red" BorderThickness="3" CornerRadius="8" Grid.Row="2" Grid.Column="0"/>
<Ellipse Fill="#FF7171EB" Stroke="#FF041374" StrokeThickness="3" Grid.Row="2" Grid.Column="1" Stretch="UniformToFill"/>
<Border BorderBrush="Red" BorderThickness="3" CornerRadius="8" Grid.Row="2" Grid.Column="1"/>
<Ellipse Fill="#FF7171EB" Stroke="#FF041374" StrokeThickness="3" Grid.Row="2" Grid.Column="2" Stretch="UniformToFill"/>
<Border BorderBrush="Red" BorderThickness="3" CornerRadius="8" Grid.Row="2" Grid.Column="2"/>
<Ellipse Fill="#FF7171EB" Stroke="#FF041374" StrokeThickness="3" Grid.Row="2" Grid.Column="3" Stretch="UniformToFill"/>
<Border BorderBrush="Red" BorderThickness="3" CornerRadius="8" Grid.Row="2" Grid.Column="3"/>
</Grid>
As an alternative solution (if somebody will find this question later) to prevent BorderThickness from scaling, you can use a custom version of Viewbox with a special converter.
Usual Viewbox, but now with a read-only Scale property and a static ThicknessConverter:
public class BorderyViewbox : Decorator {
public static readonly DependencyProperty StretchProperty = DependencyProperty.Register(nameof(Stretch),
typeof(Stretch), typeof(BorderyViewbox), new FrameworkPropertyMetadata(Stretch.Uniform, FrameworkPropertyMetadataOptions.AffectsMeasure));
public Stretch Stretch {
get { return (Stretch)GetValue(StretchProperty); }
set { SetValue(StretchProperty, value); }
}
public static readonly DependencyProperty StretchDirectionProperty = DependencyProperty.Register(nameof(StretchDirection),
typeof(StretchDirection), typeof(BorderyViewbox), new FrameworkPropertyMetadata(StretchDirection.Both, FrameworkPropertyMetadataOptions.AffectsMeasure));
public StretchDirection StretchDirection {
get { return (StretchDirection)GetValue(StretchDirectionProperty); }
set { SetValue(StretchDirectionProperty, value); }
}
public static readonly DependencyPropertyKey ScalePropertyKey = DependencyProperty.RegisterReadOnly(nameof(Scale), typeof(Size),
typeof(BorderyViewbox), new PropertyMetadata(default(Size)));
public static readonly DependencyProperty ScaleProperty = ScalePropertyKey.DependencyProperty;
public Size Scale => (Size)GetValue(ScaleProperty);
private ContainerVisual InternalVisual {
get {
if (_internalVisual == null) {
_internalVisual = new ContainerVisual();
AddVisualChild(_internalVisual);
}
return _internalVisual;
}
}
private UIElement InternalChild {
get {
var vc = InternalVisual.Children;
return vc.Count != 0 ? vc[0] as UIElement : null;
}
set {
var vc = InternalVisual.Children;
if (vc.Count != 0) vc.Clear();
vc.Add(value);
}
}
private Transform InternalTransform {
get { return InternalVisual.Transform; }
set { InternalVisual.Transform = value; }
}
public override UIElement Child {
get { return InternalChild; }
set {
var old = InternalChild;
if (!ReferenceEquals(old, value)) {
RemoveLogicalChild(old);
if (value != null) {
AddLogicalChild(value);
}
InternalChild = value;
InvalidateMeasure();
}
}
}
protected override int VisualChildrenCount => 1;
protected override Visual GetVisualChild(int index) {
if (index != 0) throw new ArgumentOutOfRangeException(nameof(index));
return InternalVisual;
}
protected override IEnumerator LogicalChildren => InternalChild == null ? EmptyEnumerator.Instance : new SingleChildEnumerator(InternalChild);
protected override Size MeasureOverride(Size constraint) {
var child = InternalChild;
var parentSize = new Size();
if (child != null) {
var infinteConstraint = new Size(double.PositiveInfinity, double.PositiveInfinity);
child.Measure(infinteConstraint);
var childSize = child.DesiredSize;
var scale = ComputeScaleFactor(constraint, childSize, Stretch, StretchDirection);
SetValue(ScalePropertyKey, scale);
parentSize.Width = scale.Width * childSize.Width;
parentSize.Height = scale.Height * childSize.Height;
}
return parentSize;
}
protected override Size ArrangeOverride(Size arrangeSize) {
var child = InternalChild;
if (child != null) {
var childSize = child.DesiredSize;
var scale = ComputeScaleFactor(arrangeSize, childSize, Stretch, StretchDirection);
SetValue(ScalePropertyKey, scale);
InternalTransform = new ScaleTransform(scale.Width, scale.Height);
child.Arrange(new Rect(new Point(), child.DesiredSize));
arrangeSize.Width = scale.Width * childSize.Width;
arrangeSize.Height = scale.Height * childSize.Height;
}
return arrangeSize;
}
private static Size ComputeScaleFactor(Size availableSize, Size contentSize, Stretch stretch, StretchDirection stretchDirection) {
var scaleX = 1.0;
var scaleY = 1.0;
var isConstrainedWidth = !double.IsPositiveInfinity(availableSize.Width);
var isConstrainedHeight = !double.IsPositiveInfinity(availableSize.Height);
if ((stretch == Stretch.Uniform || stretch == Stretch.UniformToFill || stretch == Stretch.Fill)
&& (isConstrainedWidth || isConstrainedHeight)) {
scaleX = Equals(0d, contentSize.Width) ? 0.0 : availableSize.Width / contentSize.Width;
scaleY = Equals(0d, contentSize.Height) ? 0.0 : availableSize.Height / contentSize.Height;
if (!isConstrainedWidth) {
scaleX = scaleY;
} else if (!isConstrainedHeight) {
scaleY = scaleX;
} else {
switch (stretch) {
case Stretch.Uniform:
var minscale = scaleX < scaleY ? scaleX : scaleY;
scaleX = scaleY = minscale;
break;
case Stretch.UniformToFill:
var maxscale = scaleX > scaleY ? scaleX : scaleY;
scaleX = scaleY = maxscale;
break;
case Stretch.Fill:
break;
}
}
switch (stretchDirection) {
case StretchDirection.UpOnly:
if (scaleX < 1.0) scaleX = 1.0;
if (scaleY < 1.0) scaleY = 1.0;
break;
case StretchDirection.DownOnly:
if (scaleX > 1.0) scaleX = 1.0;
if (scaleY > 1.0) scaleY = 1.0;
break;
case StretchDirection.Both:
break;
}
}
return new Size(scaleX, scaleY);
}
private ContainerVisual _internalVisual;
#region Converter-related stuff
private class ConverterInner : IValueConverter {
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
if (!(value is Size)) return parameter;
var scale = (Size)value;
var thickness = parameter as Thickness? ?? new Thickness(1d);
return new Thickness(thickness.Left / scale.Width, thickness.Top / scale.Height,
thickness.Right / scale.Width, thickness.Bottom / scale.Height);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
if (!(value is Size)) return parameter;
var scale = (Size)value;
var thickness = parameter as Thickness? ?? new Thickness(1d);
return new Thickness(thickness.Left * scale.Width, thickness.Top * scale.Height,
thickness.Right * scale.Width, thickness.Bottom * scale.Height);
}
}
public static IValueConverter ThicknessConverter { get; } = new ConverterInner();
#endregion
}
Usage example:
<BorderyViewbox x:Name="Viewbox">
<Border BorderBrush="Red" SnapsToDevicePixels="True">
<Border.BorderThickness>
<Binding Path="Scale" ElementName="Viewbox" Converter="{x:Static BorderyViewbox.ThicknessConverter}">
<Binding.ConverterParameter>
<Thickness>3</Thickness>
</Binding.ConverterParameter>
</Binding>
</Border.BorderThickness>
</Border>
</BorderyViewbox>
Shorter version using static resource:
<Thickness x:Key="BorderThickness">3</Thickness>
<BorderyViewbox x:Name="Viewbox">
<Border BorderBrush="Red" SnapsToDevicePixels="True"
BorderThickness="{Binding Path=Scale, ElementName=Viewbox,
Converter={x:Static BorderyViewbox.ThicknessConverter},
ConverterParameter={StaticResource BorderThickness}}" />
</BorderyViewbox>
The solution is to split content and border. Once it's done, set the border's width and height to grid actualWidth and Height with binding from inside the viewbox :
<Grid>
<Viewbox>
<Border
Width="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Grid}}, Path=ActualWidth}"
Height="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Grid}}, Path=ActualHeight}"
Background="{StaticResource TcsFilledColor}"
BorderBrush="{StaticResource TcsBaseColor}"
BorderThickness="10">
</Border>
</Viewbox>
<Viewbox>
<Label
Padding="10"
Style="{StaticResource BaseLabelStyle}">
<TextBlock
Style="{StaticResource BaseTextBlockStyle}"
Text="{Binding SomeText, FallbackValue=SomeText}" />
</Label>
</Viewbox>
</Grid>
Hope this helps ;)

Resources