I apologize for the length of this post but this one bums me out for two days straight now. Consider the image below. On Mouseclick on one of the tiles 1-4 the tiles resize and a big tile 5 appears in the middle. Another mouseclick reverses the process.
First I tried to bind the width/height property of row- and columndefinitions directly. This didn't work at all. The current solution uses the width and height property of labels to get the resizing done. The code is as follows...
XAML:
....
<Grid Name ="MainGrid" Background="Crimson">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid Name="LeftGrid" Grid.Column ="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1"/>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="1"/>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Label Grid.Column ="1" Grid.Row ="0" Background ="Cyan " Width="200" Name="HandleLeftTop" />
<Label Grid.Column ="0" Grid.Row ="1" Background ="Cyan " Width="200" Name="HandleLeftSideTop" />
<Label Grid.Column ="0" Grid.Row ="2" Background ="Cyan " Width="200" Name="HandleLeftSideBottom"/>
<Grid Grid.Column ="1" Grid.Row ="1" Background ="Green" MouseDown="Grid_MouseDown"> </Grid>
<Grid Grid.Column ="1" Grid.Row ="2" Background ="Yellow" MouseDown="Grid_MouseDown_1"></Grid>
</Grid>
<Grid Name="RightGrid" Grid.Column ="2">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="1"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="1"/>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Label Grid.Column ="0" Grid.Row ="0" Background ="Cyan " Width="200" Name="HandleRightTop"/>
<Label Grid.Column ="1" Grid.Row ="1" Background ="Cyan " Width="200" Name="HandleRightSideTop"/>
<Label Grid.Column ="1" Grid.Row ="2" Background ="Cyan " Width="200" Name="HandleRightSideBottom"/>
<Grid Grid.Column ="0" Grid.Row ="1" Background ="Thistle " MouseDown="Grid_MouseDown_2"></Grid>
<Grid Grid.Column ="0" Grid.Row ="2" Background ="Tan " MouseDown="Grid_MouseDown_3"></Grid>
</Grid>
<Grid Name="MiddleGrid" Grid.Column ="1">
<Grid.RowDefinitions>
<RowDefinition Height="1"/>
<RowDefinition />
</Grid.RowDefinitions>
<Label Grid.Row ="0" Background ="Cyan " Width="200" Name="HandleMiddleTop" />
<Grid Grid.Column ="0" Grid.Row ="1" Background ="Tomato"/>
</Grid>
</Grid>
C#:
public partial class RTGraphControl : UserControl
{
private readonly RTGraphControlViewModel _viewModel;
public RTGraphControl()
{
InitializeComponent();
_viewModel = new RTGraphControlViewModel(this);
DataContext = _viewModel;
//.... Binding row heights etc...
var leftColumnWidthbindingElement = new Binding
{
Source = _viewModel,
Path = new PropertyPath("LeftColumnWidth"),
Mode = BindingMode.OneWay,
UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
};
HandleLeftTop.SetBinding(WidthProperty, leftColumnWidthbindingElement);
// same for right and middle column
_viewModel.Expanded = false;
}
}
public class RTGraphControlViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private readonly RTGraphControl _rt;
private bool _expanded;
private double _rowHeight;
private double _leftcolumnWidth;
private double _middlecolumnWidth;
private double _rightcolumnWidth;
public RTGraphControlViewModel(RTGraphControl rt)
{
_rt = rt;
}
public bool Expanded
{
get { return _expanded; }
set
{
_expanded = value;
double width = _rt.MainGrid.ActualWidth;
if (_expanded)
{
LeftColumnWidth = width*0.2;
RightColumnwidth = width*0.2;
MiddleColumnWidth = width*0.6;
}
else
{
LeftColumnWidth = width * 0.5;
RightColumnwidth = width * 0.5;
MiddleColumnWidth = width * 0;
}
OnPropertyChanged("Expanded");
}
}
public double LeftColumnWidth
{
get { return _leftcolumnWidth; }
set
{
_leftcolumnWidth = value;
OnPropertyChanged("LeftColumnWidth");
}
}
public double MiddleColumnWidth {...}
public double RightColumnwidth {...}
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
This kind of works for the left and middle column but funnily enough it doesn't for the right column. The right column doesn't change its width at all. Another problem is that after initialization of the usercontrol actualwidth is set to 0. A workaround with .Measure and .Arrange didn't work.
Thanks in advance
Jon
You could define your XAML like this:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid Grid.Column="0" Grid.Row="0" Background="ForestGreen" Margin="2"
MouseDown="OuterContainer_OnMouseDown" />
<Grid Grid.Column="2" Grid.Row="0" Background="LimeGreen" Margin="2"
MouseDown="OuterContainer_OnMouseDown" />
<Grid Grid.Column="0" Grid.Row="1" Background="Firebrick" Margin="2"
MouseDown="OuterContainer_OnMouseDown" />
<Grid Grid.Column="2" Grid.Row="1" Background="OrangeRed" Margin="2"
MouseDown="OuterContainer_OnMouseDown" />
<Grid Grid.Column="1" Grid.Row="0" Grid.RowSpan="2" Background="DodgerBlue"
MouseDown="MiddleContainer_OnMouseDown" x:Name="MiddleContainer"
Visibility="Collapsed" Width="300" Margin="2" />
</Grid>
Then a little code-behind to show/hide the middle box:
private void OuterContainer_OnMouseDown(object sender, MouseButtonEventArgs e)
{
MiddleContainer.Visibility = Visibility.Visible;
}
private void MiddleContainer_OnMouseDown(object sender, MouseButtonEventArgs e)
{
MiddleContainer.Visibility = Visibility.Collapsed;
}
Hidden:
Showing:
The only caveat is that the middle box has a preset size (300, but you can change that), instead of 60%. Not sure what you're intending to do with it, so that may or may not be an issue.
Related
I am doing a project where I have to change button colors based on sliders in WPF. This is my XAML design.
XAML file
So, I have made 64 buttons, and I have tried implementing multiple options, and none worked for me.
I have this xaml code:
<Grid Grid.Column="0" Grid.RowSpan="4" Grid.ColumnSpan="4" HorizontalAlignment="Left" Height="790" Margin="0,10,0,0" Grid.Row="0" VerticalAlignment="Top" Width="800">
<Grid Margin="230,114,230,346" AutomationProperties.Name="ledMatrix" Tag="ledMatrix" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Button Grid.Column="0" Grid.Row="0" Height="40" Width="40" Command="{Binding LEDBtn}" Background="#FFAAAAAA" Tag="LED00" Click="changeLedIndicatiorColor" x:Name="LEDButton"/>
<Button Grid.Column="1" Grid.Row="0" Height="40" Width="40" Command="{Binding LEDBtn}" Background="#FFAAAAAA" Tag="LED01"/>
<Button Grid.Column="2" Grid.Row="0" Height="40" Width="40" Command="{Binding LEDBtn}" Background="#FFAAAAAA" Tag="LED02"/>
<Button Grid.Column="3" Grid.Row="0" Height="40" Width="40" Command="{Binding LEDBtn}" Background="#FFAAAAAA" Tag="LED03"/>
<Button Grid.Column="4" Grid.Row="0" Height="40" Width="40" Command="{Binding LEDBtn}" Background="#FFAAAAAA" Tag="LED04"/>
<Button Grid.Column="5" Grid.Row="0" Height="40" Width="40" Command="{Binding LEDBtn}" Background="#FFAAAAAA" Tag="LED05"/>
<Button Grid.Column="6" Grid.Row="0" Height="40" Width="40" Command="{Binding LEDBtn}" Background="#FFAAAAAA" Tag="LED06"/>
<Button Grid.Column="7" Grid.Row="0" Height="40" Width="40" Command="{Binding LEDBtn}" Background="#FFAAAAAA" Tag="LED07"/>
and sliders:
<Grid Margin="230,480,230,170">
<Slider x:Name="SeekR" Margin="0,0,0,120" Tag="seekR" Maximum="255" Background="Red" ></Slider>
<Slider x:Name="SeekG" Margin="0,50,0,70" Tag="seekG" Maximum="255" Background="Green"></Slider>
<Slider x:Name="SeekB" Margin="0,100,0,20" Tag="seekB" Maximum="255" Background="Blue"></Slider>
</Grid>
I have tried placing this in my xaml.cs file :
public void changeColor()
{
byte rr = (byte)SeekR.Value;
byte gg = (byte)SeekG.Value;
byte bb = (byte)SeekB.Value;
Color cc = Color.FromRgb(rr, gg, bb); //Create object of Color class.
SolidColorBrush colorBrush = new SolidColorBrush(cc); //Creating object of SolidColorBruch class.
LEDButton.Background = colorBrush; //Setting background of stack panel.
}
private void changeLedIndicatiorColor(object sender, RoutedEventArgs e)
{
changeColor();
}
But from this code, I have to name all the buttons differently butI want to have the same binding for all buttons and try to connect it all together, so for example I would like to set color by sliders and when I click the button color would change. Then, I can change the color, and make other buttons that different color.
Refactor ChangeColor to accept a Button, the button to change the color for:
private void ChangeLedIndicatiorColor_OnClick(object sender, RoutedEventArgs e)
{
ChangeColor(sender as Button);
}
public void ChangeColor(Button button)
{
byte rr = (byte)SeekR.Value;
byte gg = (byte)SeekG.Value;
byte bb = (byte)SeekB.Value;
Color cc = Color.FromRgb(rr, gg, bb);
SolidColorBrush colorBrush = new SolidColorBrush(cc);
button.Background = colorBrush;
}
Then register the ChangeLedIndicatiorColor event handler for each Button.Click:
...
<Button Click="ChangeLedIndicatiorColor" />
<Button Click="ChangeLedIndicatiorColor" />
<Button Click="ChangeLedIndicatiorColor" />
...
You can use the EventSetter so that the event can be applicable to all the buttons. You don't need to attach the click event handler to each button anymore.
<Window.Resources>
<Style TargetType="Button">
<EventSetter Event="Click" Handler="ChangeLedIndicatiorColor"/>
</Style>
</Window.Resources>
And inside event handler you can change the color of the button which triggered the click event.
private void changeLedIndicatiorColor(object sender, RoutedEventArgs e)
{
byte rr = (byte)SeekR.Value;
byte gg = (byte)SeekG.Value;
byte bb = (byte)SeekB.Value;
Color cc = Color.FromRgb(rr, gg, bb);
SolidColorBrush colorBrush = new SolidColorBrush(cc);
(sender as Button).Background = colorBrush;
}
I know how I can get screen dimensions from code. But how can I pass those numbers to XAML so that I can draw the screen correctly? I am trying to make a basic grid that has 3 rows. The middle one's height should be same as device screen width. What I have now is:
<Grid BackgroundColor="Black">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="I DONT KNOW WHAT TO PUT HERE :S" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Grid.Row="1" BackgroundColor="Blue" Margin="10" />
</Grid>
To me this seems like a really basic thing, but I can't find any examples on how to do this.
You can get the device info by Xamarin.Essentials: Device Display Information, create a struct called Constant and define the ScreenWidth and ScreenHeight there.
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
// Get Metrics
var mainDisplayInfo = DeviceDisplay.MainDisplayInfo;
// Orientation (Landscape, Portrait, Square, Unknown)
var orientation = mainDisplayInfo.Orientation;
// Rotation (0, 90, 180, 270)
var rotation = mainDisplayInfo.Rotation;
// Width (in pixels)
var width = mainDisplayInfo.Width;
// Height (in pixels)
var height = mainDisplayInfo.Height;
// Screen density
var density = mainDisplayInfo.Density;
}
}
public struct Constant
{
public static double ScreenWidth = DeviceDisplay.MainDisplayInfo.Width / DeviceDisplay.MainDisplayInfo.Density;
public static double ScreenHeight = DeviceDisplay.MainDisplayInfo.Height / DeviceDisplay.MainDisplayInfo.Density;
}
Use it in xaml:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:local="clr-namespace:App105"
x:Class="App105.MainPage">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="{Binding Source={x:Static local:Constant.ScreenWidth}}" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Text="Top Left" BackgroundColor="Red" Grid.Row="0" Grid.Column="0" />
<Label Text="Top Right" BackgroundColor="Blue" Grid.Row="0" Grid.Column="1" />
<Label Text="middle Left" BackgroundColor="Green" Grid.Row="1" Grid.Column="0" />
<Label Text="middle Right" BackgroundColor="Yellow" Grid.Row="1" Grid.Column="1" />
<Label Text="Bottom Left" BackgroundColor="Orange" Grid.Row="2" Grid.Column="0" />
<Label Text="Bottom Righ" BackgroundColor="Pink" Grid.Row="2" Grid.Column="1" />
</Grid>
</ContentPage>
I am currently working with a list that i bind through my viewmodel and then a service.
In the list i bind an image and a label. I can successfully get the label binded, but the image does not show. The reason for this seems to be because i change the bindingcontext in the grid where the image is nested inside. I change the bindingcontext in order to get an accurate width for the image.
If i move the image outside the grid, then it shows, so now i am trying to get the bindingcontext in order again.
What i tried to do with the image was to add a new bindingcontext
BindingContext="{x:Reference Name=gridFollowers}" Source="{Binding image}"
where gridFollowers is what i name my stacklayout where the original binding is made, but unfortunately the image still does not show.
here is the full code:
<StackLayout x:Name="gridFollowers"
BindableLayout.ItemsSource="{Binding headerService.CurrentHeader}">
<BindableLayout.ItemTemplate >
<DataTemplate>
<Grid WidthRequest="75">
<Grid.RowDefinitions>
<RowDefinition Height="8*" />
<RowDefinition Height="2*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="7.5*" />
</Grid.ColumnDefinitions>
<Grid
Grid.Row="0"
Grid.Column="0"
BindingContext="{x:Reference Name=headerImage}"
WidthRequest="{Binding Height}">
<ffimageloading:CachedImage
x:Name="headerImage" BindingContext="{x:Reference Name=gridFollowers}"
Source="{Binding image}" />
</Grid>
<Label Grid.Row="1" Grid.Column="0"
Text="{Binding firstname}" />
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
How can i make it so the image shows?
I try your code and modify some code as following, please replace your code.
<Grid
Grid.Row="0"
Grid.Column="0"
WidthRequest="{Binding Height, Source={x:Reference headerImage}}">
<ffimageloading:CachedImage x:Name="headerImage" Source="{Binding image}" />
</Grid>
Update:
please check headerService.CurrentHeader data.
Please check if binding viewmodel to page.cs bindingcontext by code behind.
<Grid.RowDefinitions>
<RowDefinition Height="8*" />
<RowDefinition Height="2*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="7.5*" />
</Grid.ColumnDefinitions>
<Grid
Grid.Row="0"
Grid.Column="0"
WidthRequest="{Binding Height, Source={x:Reference headerImage}}">
<ffimageloading:CachedImage x:Name="headerImage" Source="{Binding image}" />
</Grid>
<Label
Grid.Row="1"
Grid.Column="0"
Text="{Binding firstname}" />
</Grid>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
public partial class Page8 : ContentPage
{
public ObservableCollection<imagemodel> models { get; set; }
public Page8 ()
{
InitializeComponent ();
models = new ObservableCollection<imagemodel>()
{
new imagemodel(){firstname="first image", image="a1.jpg"},
new imagemodel(){firstname="second image",image="a2.jpg"}
};
this.BindingContext = this;
}
}
public class imagemodel
{
public string firstname { get; set; }
public string image { get; set; }
}
I need to print some informations, and I have print preview page which contains:
<Grid Name="pageGrid" Width="Auto" Height="Auto" Margin="70">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Grid.Column="0" Grid.Row="0" Name="headerGrid" Margin="0,0,0,5" />
<Grid Grid.Column="0" Grid.Row="1" Name="pageSummaryGrid" Margin="0" />
<Grid Grid.Column="0" Grid.Row="2" Name="dataGrid" Margin="0" />
<Grid Grid.Column="0" Grid.Row="3" Name="footerGrid" Margin="0,5,0,0" VerticalAlignment="Bottom" />
</Grid>
The header and footer exists on every page. pageSummaryGrid and dataGrid may be populated. Also I have this code which populate print details:
pageCount = pages.Count;
for (int i = 0; i < pageCount; i++)
{
myPage = new PrintPreviewPage();
header = new PrintPageHeader();
footer = new PrintPageFooter();
CreateHeaderAndFooter(i + 1, pageCount, header, footer);
myPage.SetHeader(header);
myPage.SetTableData(pages[i]);
myPage.SetFooter(footer);
pageList.Add(myPage);
}
Methods:
public void SetTableData(Panel panel)
{
dataGridGrid.Children.Add(panel);
}
public void SetHeader(FrameworkElement header)
{
headerGrid.Children.Add(header);
}
public void SetFooter(FrameworkElement footer)
{
footerGrid.Children.Add(footer);
}
pages is list of StackPanel(represent print details, for example some pictures,list etc.) When some pages[i] is larger than real page height then the footer becomes invisible and print details(list,pictures etc.) is cutted(footer is pushed).
I want that footer is always visible, and if I need to cut just print details. I tried to set MaxHeight, Height, ActualHeight and ClipToBounds properties of StackPanel, but nothing works. Any idea?
I'm trying to do a Window with a transparent square inside it, and I want to allow the user to re-size it in whatever way s/he wants. This code is working for vertical and horizontal re-size
<Window x:Class="TransparentWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="PloofTAS" Height="355" Width="539" Topmost="True"
ResizeMode="NoResize"
AllowsTransparency="True"
Background="Transparent"
WindowStyle="None" MouseLeftButtonDown="Window_MouseLeftButtonDown">
<Grid Name="GlobalGrid">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="8" />
<RowDefinition Height="*" />
<RowDefinition Height="8" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="8" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="8" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Rectangle Fill="Gray" Grid.Column="0" Grid.RowSpan="5" />
<Rectangle Fill="Gray" Grid.Column="4" Grid.RowSpan="5" />
<Rectangle Fill="Gray" Grid.Column="1" Grid.Row="0" Grid.ColumnSpan="3" />
<Rectangle Fill="Gray" Grid.Column="1" Grid.Row="4" Grid.ColumnSpan="3" />
<GridSplitter Grid.Column="2" Grid.Row="1" Height="Auto" HorizontalAlignment="Stretch" />
<GridSplitter Grid.Column="1" Grid.Row="2" Height="Auto" HorizontalAlignment="Stretch" />
<GridSplitter Grid.Column="3" Grid.Row="2" Height="Auto" HorizontalAlignment="Stretch" />
<GridSplitter Grid.Column="2" Grid.Row="3" Height="Auto" HorizontalAlignment="Stretch" />
<Rectangle Fill="Orange" Grid.Row="1" Grid.Column="1" />
<Rectangle Fill="Orange" Grid.Row="1" Grid.Column="3" />
<Rectangle Fill="Orange" Grid.Row="3" Grid.Column="1" />
<Rectangle Fill="Orange" Grid.Row="3" Grid.Column="3" />
<Rectangle Fill="Transparent" Stroke="Red" Grid.Column="2" Grid.Row="2"/>
</Grid>
</Window>
Here is the resulting window
I'd like for the orange squares (the corners of the red/transparent square) to be able to work diagonally, or both vertical and horizontal. Is it possible?
I don't know elegant solution for this problem as GridSplitter is not possible to set up programmatically.
My solution is just dirty mouse capture and set Column and Row measures according to mouse movement.
Set style and events. Tag property store index of a row and column we gonna to change in code behind.
<Window.Resources>
<Style x:Key="DiagonalSplitterRectangle" TargetType="{x:Type Rectangle}">
<Setter Property="Fill" Value="Orange"/>
<EventSetter Event="MouseDown" Handler="UIElement_OnMouseDown"/>
<EventSetter Event="MouseMove" Handler="UIElement_OnMouseMove"/>
<EventSetter Event="MouseUp" Handler="UIElement_OnMouseUp"/>
<EventSetter Event="LostMouseCapture" Handler="UIElement_OnLostMouseCapture"/>
</Style>
</Window.Resources>
<Rectangle Grid.Row="1" Grid.Column="1" Style="{StaticResource DiagonalSplitterRectangle}" Tag="0,0"/>
<Rectangle Grid.Row="1" Grid.Column="3" Style="{StaticResource DiagonalSplitterRectangle}" Tag="0,4"/>
<Rectangle Grid.Row="3" Grid.Column="1" Style="{StaticResource DiagonalSplitterRectangle}" Tag="4,0"/>
<Rectangle Grid.Row="3" Grid.Column="3" Style="{StaticResource DiagonalSplitterRectangle}" Tag="4,4"/>
Simple mouse capture events:
private bool _isMouseCaptured;
public MainWindow()
{
InitializeComponent();
}
private void UIElement_OnMouseDown(object sender, MouseButtonEventArgs e)
{
var uiElement = sender as UIElement;
if (uiElement == null)
return;
if (uiElement.CaptureMouse())
_isMouseCaptured = true;
}
private void UIElement_OnMouseMove(object sender, MouseEventArgs e)
{
if (!_isMouseCaptured)
return;
var clientWindow = Content as FrameworkElement;
if (clientWindow == null)
return;
var rectangle = sender as Rectangle;
if (rectangle == null)
return;
Point position = Mouse.GetPosition(GlobalGrid); ;
if (position.X < 0 || position.Y < 0 || position.X > clientWindow.ActualWidth || position.Y > clientWindow.ActualHeight)
return;
GridUpdate(position, rectangle, clientWindow);
}
private void UIElement_OnMouseUp(object sender, MouseButtonEventArgs e)
{
if (!_isMouseCaptured)
return;
var uiElement = sender as UIElement;
if (uiElement == null)
return;
uiElement.ReleaseMouseCapture();
}
private void UIElement_OnLostMouseCapture(object sender, MouseEventArgs e)
{
_isMouseCaptured = false;
}
Resize grid columns and rows according to value stored in rectangle.Tag property.
For correct behavior was needed to change opposite column and row measures too.
private void GridUpdate(Point position, Rectangle rectangle, FrameworkElement clientWindow)
{
var gridPosition = new GridPosition(rectangle.Tag.ToString());
var oppositeGridPosition = GetOppositeGridPosition(gridPosition);
var rowHeight = GetMeasure(gridPosition.Row, position.Y, clientWindow.ActualHeight);
var columnWidth = GetMeasure(gridPosition.Column, position.X, clientWindow.ActualWidth);
var oppositeRowHeight = GlobalGrid.RowDefinitions[oppositeGridPosition.Row].ActualHeight;
var oppositeColumnWidth = GlobalGrid.ColumnDefinitions[oppositeGridPosition.Column].ActualWidth;
GlobalGrid.RowDefinitions[gridPosition.Row].Height = new GridLength(rowHeight);
GlobalGrid.ColumnDefinitions[gridPosition.Column].Width = new GridLength(columnWidth);
GlobalGrid.RowDefinitions[oppositeGridPosition.Row].Height = new GridLength(oppositeRowHeight);
GlobalGrid.ColumnDefinitions[oppositeGridPosition.Column].Width = new GridLength(oppositeColumnWidth);
}
private GridPosition GetOppositeGridPosition(GridPosition gridPosition)
{
var row = (gridPosition.Row == 0) ? 4 : 0;
var column = (gridPosition.Column == 0) ? 4 : 0;
return new GridPosition(row, column);
}
private double GetMeasure(int gridPosition, double position, double windowMeasure)
{
return gridPosition == 0 ? position : windowMeasure - position;
}
GridPosition is structure that stores column and row index values.
public struct GridPosition
{
public int Row { get; private set; }
public int Column { get; private set; }
public GridPosition(int row, int column)
: this()
{
Row = row;
Column = column;
}
public GridPosition(string gridPostion)
: this()
{
Row = Convert.ToInt32(gridPostion.Split(',')[0]);
Column = Convert.ToInt32(gridPostion.Split(',')[1]);
}
}