I'm trying to make a grid where you can adjust the number of rows and columns using a slider. I have no syntax errors in my code, however it is not doing what i want it to. The grid and slider have the following XAML code:
<Window x:Class="Neural_Network_Investigation.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:Neural_Network_Investigation"
mc:Ignorable="d"
Title="MainWindow"
Height="Auto"
MaxHeight="520" MinHeight="450"
Width="Auto"
MaxWidth="700" MinWidth="630">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="300"/>
<RowDefinition Height="100"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="300"/>
<ColumnDefinition Width="300"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border Grid.Row="0"
Grid.Column="0"
Grid.RowSpan="4"
Grid.ColumnSpan="4" Background="Gray"/>
<Grid Grid.Column="1"
Grid.Row="1"
x:Name="NetworkGrid"
ShowGridLines="True"/>
<StackPanel Grid.Column="1"
Grid.Row="2"
Orientation="Vertical"
HorizontalAlignment="Left"
VerticalAlignment="Center">
<StackPanel Orientation="Horizontal">
<TextBlock FontSize="12"
Text="Grid Size: "/>
<TextBlock x:Name="GridSizeText"
FontSize="12" Text=""
MinWidth="15"/>
<Slider x:Name="GridSizeSlider"
Minimum="4" Maximum="20"
TickPlacement="BottomRight"
TickFrequency="1"
IsSnapToTickEnabled="True"
Width="100"
ValueChanged="GridSizeSlider_ValueChanged"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
</StackPanel>
</StackPanel>
</Grid>
</Window>
When the slider is changed, I want the number of rows and columns in NetworkGrid to be updated to match:
private void GridSizeSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
var GridSize = (int)GridSizeSlider.Value;
GridSizeText.Text = GridSize.ToString();
NetworkGrid.ColumnDefinitions.Clear();
NetworkGrid.RowDefinitions.Clear();
double SquareWidth = NetworkGrid.Width / GridSize;
double SquareHeight = NetworkGrid.Height / GridSize;
for(int columnNumber = 0; columnNumber < GridSize; columnNumber++)
{
var column = new ColumnDefinition();
NetworkGrid.ColumnDefinitions.Add(column);
for (int rowNumber = 0; rowNumber < GridSize; rowNumber++)
{
var row = new RowDefinition();
NetworkGrid.RowDefinitions.Add(row);
var square = new Border();
square.Background = Brushes.Black;
square.SetValue(Grid.ColumnProperty, columnNumber);
square.SetValue(Grid.RowProperty, rowNumber);
}
}
}
When I run the program, I see nothing despite ShowGridLines being enabled. This means that it is not adding the columns and rows to the grid. How do I fix this?
I have used code from this article: How to add rows and columns to a WPF Grid programmatically
I have also checked out this blog showcasing a class that allows you to draw a Grid with a dynamic number of rows or columns, however i cannot get my head around how to use the class in my own program.
Related
I have following WPF XAML file,
<Window x:Class="Program"
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:Program"
mc:Ignorable="d"
Title="Print Preview" Height="40820.962" Width="2135.146">
<Grid Margin="10,10,2,-21" Height="40801" VerticalAlignment="Top">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="131*"/>
<RowDefinition Height="40670*"/>
</Grid.RowDefinitions>
<Grid HorizontalAlignment="Left" Height="3438" Margin="20,126,0,0" VerticalAlignment="Top" Width="2095" Grid.RowSpan="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="500*"/>
<ColumnDefinition Width="1072*"/>
<ColumnDefinition Width="523*"/>
</Grid.ColumnDefinitions>
<Label x:Name="label5" Content="Here" Grid.Column="1" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" RenderTransformOrigin="-7.455,-0.374" Height="58" Width="171" FontSize="16"/>
</Grid>
<Grid HorizontalAlignment="Right" Height="432" Margin="0,3453,1605,0" Grid.Row="1" VerticalAlignment="Top" Width="490" RenderTransformOrigin="0.62,1.205">
<Grid.RowDefinitions>
<RowDefinition Height="143*"/>
<RowDefinition Height="136*"/>
<RowDefinition Height="153*"/>
</Grid.RowDefinitions>
</Grid>
<Grid HorizontalAlignment="Right" Height="452" Margin="0,3433,1605,0" Grid.Row="1" VerticalAlignment="Top" Width="490" RenderTransformOrigin="0.62,1.205">
<Grid.RowDefinitions>
<RowDefinition Height="143*"/>
<RowDefinition Height="136*"/>
<RowDefinition Height="153*"/>
</Grid.RowDefinitions>
</Grid>
<Grid HorizontalAlignment="Left" Height="447" Margin="1594,3438,0,0" Grid.Row="1" VerticalAlignment="Top" Width="511">
<Grid.RowDefinitions>
<RowDefinition Height="142*"/>
<RowDefinition Height="156*"/>
<RowDefinition Height="149*"/>
</Grid.RowDefinitions>
</Grid>
<Grid HorizontalAlignment="Left" Height="452" Margin="510,3433,0,0" Grid.Row="1" VerticalAlignment="Top" Width="1084">
<Grid.RowDefinitions>
<RowDefinition Height="44*"/>
<RowDefinition Height="45*"/>
</Grid.RowDefinitions>
</Grid>
<Grid HorizontalAlignment="Left" Height="23141" Margin="20,3895,0,0" Grid.Row="1" VerticalAlignment="Top" Width="1574"/>
<Grid HorizontalAlignment="Left" Height="23540" Margin="1599,3496,0,0" Grid.Row="1" VerticalAlignment="Top" Width="506">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="14.143"/>
<ColumnDefinition Width="146.857"/>
<ColumnDefinition Width="42.714"/>
<ColumnDefinition Width="119*"/>
<ColumnDefinition Width="98*"/>
<ColumnDefinition Width="85*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="87*"/>
<RowDefinition Height="23516*"/>
</Grid.RowDefinitions>
<Label x:Name="label" Content="Hespanic" HorizontalAlignment="Left" Margin="-1,-61,0,0" VerticalAlignment="Top" Height="55" Width="506" FontSize="22" Grid.ColumnSpan="6"/>
</Grid>
<Label x:Name="label1" Content="Sample" HorizontalAlignment="Left" Margin="8,97,0,0" VerticalAlignment="Top" RenderTransformOrigin="-8.5,0.654" Width="215"/>
<Label x:Name="label2" Content="Layer" HorizontalAlignment="Left" Height="33" Margin="922,10,0,0" VerticalAlignment="Top" Width="232" FontSize="18"/>
<Label x:Name="label3" Content="Index" HorizontalAlignment="Left" Margin="1969,10,0,0" VerticalAlignment="Top" Width="105"/>
<Label x:Name="label4" Content="People" HorizontalAlignment="Left" Margin="1477,84,0,0" VerticalAlignment="Top" Width="161"/>
</Grid>
</Window>
So I'm trying to add thickness = 1, outline for grid borders, rows and columns
So I tried following thread
How do i put a border on my grid in WPF?
So to add a border I added following thing, and its working fine
<Border BorderBrush="Black" BorderThickness="2">
<Grid>
<!-- Grid contents here -->
</Grid>
</Border>
But since I have need to add thickness = 1, outline for all above multiple columns and rows also, I tried something like this
</Grid.ColumnDefinitions>
<Border Grid.Row="0" Grid.Column="0" BorderThickness="1" BorderBrush="Black"/>
<Border Grid.Row="0" Grid.Column="1" BorderThickness="1" BorderBrush="Black"/>
which is identifying each column and row and add thickness to them, but this seems quite time consuming and confusing work.
Is there any other proper and quick way to add BorderThickness="1" BorderBrush="Black" to all above Columns and Rows in the grids ?
In the default WPF Grid, you can set ShowGridLines="True". However these lines are meant to be designer lines, and not meant for end use.
The common solution I use is a custom GridControl which adds DependencyProperties for GridLines settings, and overrides OnRender to draw them.
public class GridControl : Grid
{
#region Properties
public bool ShowCustomGridLines
{
get { return (bool)GetValue(ShowCustomGridLinesProperty); }
set { SetValue(ShowCustomGridLinesProperty, value); }
}
public static readonly DependencyProperty ShowCustomGridLinesProperty =
DependencyProperty.Register("ShowCustomGridLines", typeof(bool), typeof(GridControl), new UIPropertyMetadata(false));
public Brush GridLineBrush
{
get { return (Brush)GetValue(GridLineBrushProperty); }
set { SetValue(GridLineBrushProperty, value); }
}
public static readonly DependencyProperty GridLineBrushProperty =
DependencyProperty.Register("GridLineBrush", typeof(Brush), typeof(GridControl), new UIPropertyMetadata(Brushes.Black));
public double GridLineThickness
{
get { return (double)GetValue(GridLineThicknessProperty); }
set { SetValue(GridLineThicknessProperty, value); }
}
public static readonly DependencyProperty GridLineThicknessProperty =
DependencyProperty.Register("GridLineThickness", typeof(double), typeof(GridControl), new UIPropertyMetadata(1.0));
#endregion
protected override void OnRender(DrawingContext dc)
{
if (ShowCustomGridLines)
{
foreach (var rowDefinition in RowDefinitions)
{
dc.DrawLine(new Pen(GridLineBrush, GridLineThickness), new Point(0, rowDefinition.Offset), new Point(ActualWidth, rowDefinition.Offset));
}
foreach (var columnDefinition in ColumnDefinitions)
{
dc.DrawLine(new Pen(GridLineBrush, GridLineThickness), new Point(columnDefinition.Offset, 0), new Point(columnDefinition.Offset, ActualHeight));
}
dc.DrawRectangle(Brushes.Transparent, new Pen(GridLineBrush, GridLineThickness), new Rect(0, 0, ActualWidth, ActualHeight));
}
base.OnRender(dc);
}
static GridControl()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(GridControl), new FrameworkPropertyMetadata(typeof(GridControl)));
}
}
It can be used like this :
<local:GridEx ShowCustomGridLines="True"
GridLineBrush="#FF38B800"
GridLineThickness="2">
...
</local:GridEx>
I am trying to add user controls to the Grid and I am trying to set the Grid.Column and Grid.Row property in the DataTemplate but it does not have any effect on the rendering. Can someone help to point out what could be wrong in the code below.
I have the main window with the following code:
<ItemsControl ItemsSource="{Binding Controls}">
<ItemsControl.ItemsPanel >
<ItemsPanelTemplate>
<Grid Name="MainGrid">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
</Grid>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<AppControls:TagInfo Grid.Row="{Binding RowIndex}"
Grid.Column="{Binding ColumnIndex}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
TagInfo.xaml.cs
public partial class TagInfo : UserControl
{
public TagInfo()
{
InitializeComponent();
}
public int RowIndex { get; set; }
public int ColumnIndex { get; set; }
}
TagInfo.xaml
<UserControl x:Class="DataSimulator.WPF.Controls.TagInfo"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d" Height="258" Width="302"
DataContext="{Binding Main, Source={StaticResource Locator}}">
<Grid Margin="2,2,2,2">
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
<RowDefinition Height="30"/>
<RowDefinition Height="30"/>
<RowDefinition Height="30"/>
<RowDefinition Height="30"/>
<RowDefinition Height="30"/>
<RowDefinition Height="30"/>
<RowDefinition Height="30"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="Tag"/>
<TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding TagInfo.TagName}"/>
<TextBlock Grid.Row="1" Grid.Column="0" Text="High High"/>
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding TagInfo.HighHigh}"/>
<TextBlock Grid.Row="2" Grid.Column="0" Text="High"/>
<TextBox Grid.Row="2" Grid.Column="1" Text="{Binding TagInfo.High}"/>
<TextBlock Grid.Row="3" Grid.Column="0" Text="Low Low"/>
<TextBox Grid.Row="3" Grid.Column="1" Text="{Binding TagInfo.LowLow}"/>
<TextBlock Grid.Row="4" Grid.Column="0" Text="Low"/>
<TextBox Grid.Row="4" Grid.Column="1" Text="{Binding TagInfo.Low}"/>
<TextBlock Grid.Row="5" Grid.Column="0" Text="Range Start"/>
<TextBox Grid.Row="5" Grid.Column="1" Text="{Binding TagInfo.RangeStart}"/>
<TextBlock Grid.Row="6" Grid.Column="0" Text="Range End"/>
<TextBox Grid.Row="6" Grid.Column="1" Text="{Binding TagInfo.RangeEnd}"/>
<Button Grid.Row="7" Grid.Column="0" Grid.ColumnSpan="2" Content="Save"/>
</Grid>
</UserControl>
ViewModel
private ObservableCollection<Controls.TagInfo> _controls
= new ObservableCollection<Controls.TagInfo>();
public ObservableCollection<Controls.TagInfo> Controls
{
get { return _controls; }
set { _controls = value; }
}
private void AddControl()
{
if(currentRow == 3)
{
currentRow = 0;
}
if(currentColumn == 3)
{
currentColumn = 0;
currentRow++;
}
var tagInfoUserControl = new Controls.TagInfo();
tagInfoUserControl.RowIndex = currentRow;
tagInfoUserControl.ColumnIndex = currentColumn++;
_controls.Add(tagInfoUserControl);
}
I am trying to add user controls to the grid and I am trying to set the Grid.Column and Grid.Row property in the data template but it does not have any effect on the rendering
We can't do the attached property binding in a DataTemplate, creating a style for your UserControl in ItemsControl.ItemContainerStyle can make it work:
<ItemsControl ItemsSource="{Binding Controls}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid Name="MainGrid">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
</Grid>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="AppControls:TagInfo">
<Setter Property="Grid.Row" Value="{Binding RowIndex}"/>
<Setter Property="Grid.Column" Value="{Binding ColumnIndex}"/>
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
Screenshot:
when all columns and rows have to be of equal size and elements are consequtive, it is probably simpler to use UniformGrid. Rows and Columns properties support binding.
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Name="MainGrid" Rows="4" Columns="4"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
here is a nice example of Grid ItemsPanel here: WPF Grid as ItemsPanel for a list dynamically bound to an ItemsControl
Am trying to add Set of labels and images in a stackpanel in code behind.And finally am attaching that stackpanel to particular column of a grid control.My expected output should be like
<image><label>
combination
but my output is like it displays the label in first column of grid and the image in the next column.(I was not able to add the snapshots since i dont have enough reputations)
XAML code
<Window x:Class="Ping.MainWindow" WindowStyle="ThreeDBorderWindow" Icon="F:\ChatApplication\Ping\Ping\Images\title.ico" Cursor="Pen"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Ping - Connected by alphabets" Height="450" Width="750" WindowStartupLocation="CenterScreen" SizeToContent="WidthAndHeight" >
<Grid Name="grid_window">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<GridSplitter HorizontalAlignment="Right"
VerticalAlignment="Stretch"
Grid.Column="1" ResizeBehavior="PreviousAndNext"
Width="5" Background="#FFBCBCBC"/>
<TabControl Grid.ColumnSpan="2" Name="tab_control" BorderBrush="Cornsilk" BorderThickness="4" HorizontalAlignment="Left" Height="419" Margin="227,0,0,0" VerticalAlignment="Top" Width="515">
<TabItem Header="Home" BorderBrush="Green"/>
</TabControl>
</Grid>
code behind
public MainWindow()
{
InitializeComponent();
DBCoding dbobj = new DBCoding();
//Contains names {"Dhivi","Walle"}
List<string> online = new List<string>();
online = dbobj.onlineUsers();
StackPanel myStackPanel = new StackPanel();
myStackPanel.Orientation = Orientation.Vertical;
foreach (var item in online)
{
Image myImage = new Image();
myImage.Source = new BitmapImage(new Uri("F:\\ChatApplication\\Ping\\Ping\\Images\\visible.png"));
myImage.Width = 10;
myImage.Height = 10;
//myImage.Margin = new Thickness(-10,0,-80,0);
myImage.Height = 10;
Label user = new Label();
user.Content = item.ToString();
myStackPanel.Children.Add(myImage);
myStackPanel.Children.Add(user);
}
grid_window.Children.Add(myStackPanel);
Grid.SetColumnSpan(myStackPanel, 1);
Grid.SetColumn(myStackPanel, 0);
}
Can anybody tell me the solution.
Here's how your code should look like, using data binding, an ItemsControl and a DataTemplate:
XAML
<Window x:Class="Ping.MainWindow" WindowStyle="ThreeDBorderWindow" Icon="F:\ChatApplication\Ping\Ping\Images\title.ico" Cursor="Pen"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Ping - Connected by alphabets" Height="450" Width="750" WindowStartupLocation="CenterScreen" SizeToContent="WidthAndHeight" >
<Grid Name="grid_window">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<GridSplitter HorizontalAlignment="Right"
VerticalAlignment="Stretch"
Grid.Column="1" ResizeBehavior="PreviousAndNext"
Width="5" Background="#FFBCBCBC"/>
<TabControl Grid.ColumnSpan="2" Name="tab_control" BorderBrush="Cornsilk" BorderThickness="4" HorizontalAlignment="Left" Height="419" Margin="227,0,0,0" VerticalAlignment="Top" Width="515">
<TabItem Header="Home" BorderBrush="Green"/>
</TabControl>
<ItemsControl ItemsSource="{Binding}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<DockPanel>
<!-- You really should add the image as a resource to the project -->
<Image Source="F:\ChatApplication\Ping\Ping\Images\visible.png"
Width="10" Height="10" />
<TextBlock Text="{Binding}" />
</DockPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
C#
public MainWindow()
{
InitializeComponent();
DBCoding dbobj = new DBCoding();
List<string> online = dbobj.onlineUsers();
DataContext = online;
}
I got a problem with the GridSplitter
Simple example code:
<Grid x:Name="MainGrid">
<Grid.RowDefinitions>
<RowDefinition Height="100"></RowDefinition>
<RowDefinition Height="2"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Grid x:Name="TopGrid" Grid.Row="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="Red"/>
<GridSplitter ResizeDirection="Rows" Grid.Row="1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Height="2" Background="Black" />
<Grid x:Name="BottomGrid" Grid.Row="2" HorizontalAlignment="Stretch" Background="Aquamarine" VerticalAlignment="Stretch"/>
</Grid>
This creates two Grids vertically seperated by a GridSplitter.
What I want to achieve is, that the GridSplitter automaticly align to the Grid´s content.
For example if I got a collapsable element in the bottom Grid, I want the top Grid to become bigger if I collapse the element. If I expand it, the top Grid should become smaller.
How do I do this? Later I will have 4 Grids with 3 GridSplitter´s... so the solution should work with multiple GridSplitter´s as well.
[edit]:
my xaml:
<Grid x:Name="MainGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="100">
<RowDefinition.MinHeight>
<MultiBinding Converter="{StaticResource ResourceKey=MultiValueConverter}">
<Binding ElementName="dgStapelliste" Path="ActualHeight"></Binding>
</MultiBinding>
</RowDefinition.MinHeight>
</RowDefinition>
<RowDefinition Height="1"></RowDefinition>
<RowDefinition Height="*"></RowDefinition >
</Grid.RowDefinitions>
<Grid Grid.Row="0" Grid.Column="0" x:Name="Test">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="200"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<WPF:DataGrid GridHeaderContent="{Binding StapelListe.HeaderText}" SelectedItem="{Binding StapelListe.SelectedItem}" Grid.Row="0" Grid.Column="0" x:Name="dgStapelliste" HorizontalAlignment="Stretch" ItemsSource="{Binding StapelListe, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"/>
<WPF:DataGrid GridHeaderContent="{Binding EinzelListe.HeaderText}" Grid.Row="0" Grid.Column="1" x:Name="dgEinzelliste" HorizontalAlignment="Stretch" ItemsSource="{Binding EinzelListe, Mode=OneWay}"/>
<GridSplitter Grid.Column="0" Width="1" VerticalAlignment="Stretch" Background="Black" />
</Grid>
<Grid Grid.Row="2" Grid.Column="0" Grid.RowSpan="2">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="200"/>
</Grid.ColumnDefinitions>
<WPF:DataGrid GridHeaderContent="{Binding Anforderungsliste.HeaderText}" Grid.Column="0" x:Name="dgAnforderungsliste" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ItemsSource="{Binding Anforderungsliste, Mode=OneWay}"/>
<GridSplitter Grid.Column="0" Width="1" VerticalAlignment="Stretch" Background="Black" />
</Grid>
<GridSplitter Grid.Column="0" Grid.Row="1" Height="1" ResizeDirection="Rows" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Background="Black" x:Name="testSplitter" />
</Grid>
You could use MultiBinding to achieve what you want.
For each RowDefinition you set a MinHeight which is bound to its contents ActualHeight's like so:
<RowDefinition Height="100">
<RowDefinition.MinHeight>
<MultiBinding Converter="{StaticResource ResourceKey=CalcAll}">
<Binding ElementName="firstElementInThisRow" Path="ActualHeight"></Binding>
<Binding ElementName="secondElementInThisRow" Path="ActualHeight"></Binding>
<Binding ElementName="thirdElementInThisRow" Path="ActualHeight"></Binding>
<Binding ElementName="fourthElementInThisRow" Path="ActualHeight"></Binding>
</MultiBinding>
</RowDefinition.MinHeight>
</RowDefinition>
Your Converter could look like:
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
double result = 0.0;
foreach (object item in values)
{
result += System.Convert.ToDouble(item);
}
return result;
}
public object[] ConvertBack(object values, Type[] targetType, object parameter, CultureInfo culture)
{
return null;
}
Everytime you expand a control, its ActualHeight changes and the Binding gets update -> MinHeight of the parents RowDefinition changes.
But you cant set one if the controls VerticalAlignment to Stretch, because then the ActualHeight wouldn't change by expanding.
EDIT: Since the only property I can now think of is the DesiredSize.Height-property, you can't use Binding (the binding won't update, if the DesiredSize.Height-value changes).
But perhaps you can use a property (let's call it MinHeightRowOne) of type double which raises the PropertyChanged event in it's setter and is bound to the first rows MinHeight (one property for each row):
public double _minHeightRowOne;
public double MinHeightRowOne
{
get
{
return _minHeightRowOne;
}
set
{
_minHeightRowOne = value;
OnPropertyChanged("MinHeightRowOne");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string name)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
<RowDefinition Height="100" MinHeight="{Binding Path=MinHeightRowOne}"/>
Now add this EventHandler to the SizeChanged-Event of every control in the first row (one handler for each row):
private List<KeyValuePair<string,double>> oldVals = new List<KeyValuePair<string,double>>();
private void ElementInRowOneSizeChanged(object sender, SizeChangedEventArgs e)
{
FrameworkElement elem = (FrameworkElement)sender;
MinHeightRowOne -= oldVals.Find(kvp => kvp.Key == elem.Name).Value;
elem.Measure(new Size(int.MaxValue, int.MaxValue));
MinHeightRowOne += elem.DesiredSize.Height;
oldVals.Remove(oldVals.Find(kvp => kvp.Key == elem.Name));
oldVals.Add(new KeyValuePair<string, double>(elem.Name, elem.DesiredSize.Height));
}
Through this the MinHeight of the Rows get updated everytime the Size of a control changes (which should include expanding or collapsing items).
Note that every control must have an unique name to make this work.
I have the following layou:
<s:SurfaceWindow x:Class="Prototype_Concept_2.SurfaceWindow1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:s="http://schemas.microsoft.com/surface/2008"
Title="Prototype_Concept_2"
>
<s:SurfaceWindow.Resources>
<ImageBrush x:Key="WindowBackground" Stretch="None" Opacity="0.6" ImageSource="pack://application:,,,/Resources/WindowBackground.jpg"/>
</s:SurfaceWindow.Resources>
<Grid Background="{StaticResource WindowBackground}" >
<Grid Name="ProjectsGrid">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBox Name="ProjectsHeader" Grid.ColumnSpan="2" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" FontSize="25" Text="Please choose one of the following projects" Grid.Row="0"></TextBox>
<s:SurfaceButton Name="BottomButton" HorizontalAlignment="Right" FontSize="20" Width="100" Grid.Column="1" Grid.Row="2" Foreground="White" Content="Refresh"></s:SurfaceButton>
<s:SurfaceListBox Background="Black" Grid.ColumnSpan="2" Name="ProjectsList" Grid.Row="1" ItemsSource="{Binding Projects}"></s:SurfaceListBox>
<Label Name="ProjectsFooter" Grid.Column="0" Grid.Row="2" Grid.ColumnSpan="2" FontSize="15" Content="Fetching projects data ..."></Label>
</Grid>
<Grid ShowGridLines="True" Name="SmellHeader" Visibility="Collapsed">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="256"></ColumnDefinition>
<ColumnDefinition Width="256"></ColumnDefinition>
<ColumnDefinition Width="256"></ColumnDefinition>
<ColumnDefinition Width="256"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="38"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Rectangle Grid.Column="0" Grid.Row="0" Fill="Black"></Rectangle>
<Viewbox Grid.Column="0" Grid.Row="0" s:Contacts.PreviewContactDown="BrainClass_PreviewContactDown">
<Label Background="Black" Foreground="White" Content="BrainClass" HorizontalContentAlignment="Center"></Label>
</Viewbox>
<Rectangle Grid.Column="1" Grid.Row="0" Fill="Black"></Rectangle>
<Viewbox Grid.Column="1" Grid.Row="0">
<Label Background="Black" Foreground="White" Content="God Class" HorizontalContentAlignment="Center"></Label>
</Viewbox>
<Rectangle Grid.Column="2" Grid.Row="0" Fill="Black"></Rectangle>
<Viewbox Grid.Column="2" Grid.Row="0">
<Label Background="Black" Foreground="White" Content="Tradition Breaker" HorizontalContentAlignment="Center"></Label>
</Viewbox>
<Rectangle Grid.Column="3" Grid.Row="0" Fill="Black"></Rectangle>
<Viewbox Grid.Column="3" Grid.Row="0">
<Label Background="Black" Foreground="White" Content="RefusedParent Bequest" HorizontalContentAlignment="Center"></Label>
</Viewbox>
</Grid>
<Canvas Name="RootLayer" Grid.Row="1" Grid.ColumnSpan="4">
</Canvas>
</Grid>
</s:SurfaceWindow>
To the RootLayer I add some Ellipse. Later I want to reoder them:
internal void setFocus(SourceManager manager)
{
Console.WriteLine("Set focus to class " + getFullName());
foreach (SourceFile sf in manager.getBrainClasses())
{
sf.getVisualizer().Fill = Brushes.Red;
Canvas.SetZIndex(sf.getVisualizer(), 0);
}
this.getVisualizer().Fill = Brushes.Blue;
Canvas.SetZIndex(this.getVisualizer(), 1);
manager.window.RootLayer.InvalidateArrange();
manager.window.RootLayer.InvalidateVisual();
}
The Ellipse is referenced by this.getVisualizer();
However, nothing changes? How can I bring one Ellipse to the front?
It's not fully clear from your code post how the ellipses are added to the canvas but here is a small sample that does essentially what you want to do:
<Grid>
<Canvas x:Name="RootLayer" Width="500" Height="500" />
</Grid>
And in the constructor of the code behind, create some ellipses:
for (int i = 0; i < 10; i++)
{
Ellipse e = new Ellipse
{
Width = 100,
Height = 100,
Fill = new SolidColorBrush(
Color.FromArgb(0xDD,
(Byte) r.Next(255)
(Byte) r.Next(255)
(Byte) r.Next(255))),
Stroke = Brushes.Black,
StrokeThickness = 1,
};
e.MouseUp += new MouseButtonEventHandler(e_MouseUp);
Canvas.SetLeft(e, r.Next(400));
Canvas.SetTop(e, r.Next(400));
RootLayer.Children.Add(e);
}
Event handler to handle mouse click on the ellipses
void e_MouseUp(object sender, MouseButtonEventArgs e)
{
foreach (UIElement item in RootLayer.Children)
Panel.SetZIndex(item, 0);
Panel.SetZIndex((UIElement)sender, 1);
}
With the code above, whenever an ellipse is clicked (mouse up), it will raise above all the other ellipses in that canvas.