How to specify 3/4th of are for one content presenter? - wpf

I am creating a new template for Tab control
in which I need to arrange items like attached image. The style given below is to have main tabs ..and contents... While mentioning the content (content presenter) I have to specify the grid column/row...So if I use row column/row as "0","0"..then all my contents will in the left top area...
Please tell me how do I specify a content presenter with 3/4 area of the grid.
<Style x:Key="OutlookTabControlStyle" TargetType="{x:Type TabControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabControl}">
<Grid ClipToBounds="true" SnapsToDevicePixels="true"
KeyboardNavigation.TabNavigation="Local">
<Grid.RowDefinitions>
<RowDefinition x:Name="RowDefinition0" Height="Auto"/>
<RowDefinition x:Name="RowDefinition1" Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="ColumnDefinition0"/>
<ColumnDefinition x:Name="ColumnDefinition1" Width="0"/>
</Grid.ColumnDefinitions>
<Grid x:Name="ContentPanel" Grid.Column="0" Grid.Row="1">
<ContentPresenter SnapsToDevicePixels=
"{TemplateBinding SnapsToDevicePixels}" Margin="2,2,2,2"
x:Name="PART_SelectedContentHost"
ContentSource="SelectedContent"/>
</Grid>
<StackPanel HorizontalAlignment="Stretch" Margin="0,-2,0,0"
x:Name="HeaderPanel" VerticalAlignment="Bottom" Width="Auto"
Height="Auto" Grid.Row="1" IsItemsHost="True"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground"
Value="{DynamicResource
{x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
My question is how do I allocate the remaining part (other than main tabs area) as content paresenter... I can see Canvas as one option. please help me if you know more about this.

Create a Grid with two Columns: one column with a width of * and one with a width of 3*. This will make make your 2nd column 3 times the size of the first column, or 3/4 of the total size
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="3*" />
</Grid.ColumnsDefinitions>
</Grid>
As an alternative you don't want to use a Grid, I usually use a MathConverter which allows me to adjust a bound value by a mathematical formula. The code for the MathConverter can be found here
<Grid Canvas.Left="{Binding ElementName=ParentPanel, Path=ActualWidth,
Converter={StaticResource MyMathConverter},
ConverterParameter=#VALUE*.75}" />

Related

Adjusting WPF chart toolkit ColumnSeries (System.Windows.Controls.DataVisualization.Charting)

I am using the WPF chart toolkit (System.Windows.Controls.DataVisualization.Charting). All stylings are in the XAML and I only bound the data to chart from my ViewModel. Everything looks alright for the first time I click on a button to show the columnseries. When I click on the button for the second time, the chart becomes bigger/corrupted; It shows only part of the graph.
The graph is drawn for the first time:
And button clicked for the second time:
The code I am using is as below:
<dvc:Chart Cursor="Cross"
Background="#FFFFFCF2"
Title="{Binding Title}"
Height="410"
Width="750"
VerticalAlignment="Top"
Name="ChartContainer">
<dvc:Chart.Series>
<dvc:ColumnSeries ItemsSource="{Binding ChartData,UpdateSourceTrigger=PropertyChanged}"
IndependentValueBinding="{Binding Path= Key}"
DependentValueBinding="{Binding Path= Value}"
Name="SummariesChart"
Margin="0,0,0,0"
IsManipulationEnabled="False">
<dvc:ColumnSeries.DataPointStyle>
<Style TargetType="dvc:ColumnDataPoint">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="dvc:ColumnDataPoint">
<Grid>
<Rectangle Fill="{TemplateBinding Background}"
Stroke="Black" />
<Grid Margin="0,0, 0, 0"
HorizontalAlignment="Center"
VerticalAlignment="Top">
<TextBlock Text="{TemplateBinding FormattedDependentValue}"
Margin="2" />
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</dvc:ColumnSeries.DataPointStyle>
</dvc:ColumnSeries >
</dvc:Chart.Series >
<dvc:Chart.Axes>
<dvc:LinearAxis Orientation="X"
Title="{Binding XTitle}"
Interval="1"
Location="Bottom"
ShowGridLines="True" />
<dvc:LinearAxis Orientation="Y"
Title="{Binding YTitle}"
ShowGridLines="True"
Location="Left" />
</dvc:Chart.Axes>
</dvc:Chart>
Also, to give you complete idea, I used a style on top of the page as follow:
<Style TargetType="dvc:Chart">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="dvc:Chart">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<dv:Title Content="{TemplateBinding Title}"
Style="{TemplateBinding TitleStyle}"
Margin="1" />
<Grid Grid.Row="1"
Margin="1,0,1,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<primitives:EdgePanel x:Name="ChartArea">
<Grid Canvas.ZIndex="-1"
Style="{TemplateBinding PlotAreaStyle}" />
<Border Canvas.ZIndex="10"
BorderBrush="#FF919191"
BorderThickness="1" />
</primitives:EdgePanel>
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="BarDataPointStyle"
TargetType="{x:Type dvc:BarSeries}">
<Setter Property="Background"
Value="Blue"></Setter>
<Setter Property="Opacity"
Value="0" />
</Style>
When I remove <dvc:Chart.Axes> block, it works correctly consistently. But I need X-axe and Y-axes descriptions existing in this code block. Do you know how I can tackle this problem? I appreciate your help.
I found a way to resolve the issue. But still, I am skeptical that something is wrong with the styling or something.
I added Minimum = 0 and Maximum in LinearAxis tag. I bounded Maximum to a variable in my ViewModel. I got the length of the array and added one to the maximum variable(MaxNumberInXAxes).
<dvc:LinearAxis Orientation="X"
Title="{Binding XTitle}" I
nterval="{Binding XAxisInterval}"
Location="Bottom"
ShowGridLines="True"
AllowDrop="False"
Minimum="0"
Maximum="{Binding MaxNumberInXAxes}"/>
The graph becomes something like this:

Why does my ControlTemplate for Grid not work?

I want to set the ControlTemplate of grid to look like this:
Here is the markup:
<Grid>
<Grid.Style>
<Style TargetType="Grid">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Grid ShowGridLines="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.1*"></ColumnDefinition>
<ColumnDefinition Width="0.8*"></ColumnDefinition>
<ColumnDefinition Width="0.1*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="0.1*"></RowDefinition>
<RowDefinition Height="0.8*"></RowDefinition>
<RowDefinition Height="0.1*"></RowDefinition>
</Grid.RowDefinitions>
<ContentPresenter Grid.Row="1" Grid.Column="1"></ContentPresenter>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Style>
<Border Background="Red"></Border>
</Grid>
I don't know why the ControlTemplate doesn't work. Is there something wrong with my markup?
Grid.RowDefinitions and Grid.ColumnDefinitions are no Dependency properties, and can't be set by a Style. I guess this is why you used a ControlTemplate instead of setting it directly. But the default Style of the ControlTemplate does not show any Borders/Lines, therefore you may want to use a ContentPresenter (Wrap it around your Grid and not inside of it).
Additionally: To place the Border in the Center of the Grid, you must set the Row and Column, otherwise the Border is spread across the whole Grid. And place it right there where you have your ContentPresenter inside the Controltemplate, not outside of it.
Edit
Due to the clarification in the comments i suggest to use a Border which shrinks the Content with a RenderTransform.
Style
<Style x:Name="Shrink80pcBorder" TargetType="{x:Type Border}">
<Setter Property="RenderTransformOrigin" Value="0.5,0.5"/>
<Setter Property="RenderTransform">
<Setter.Value>
<ScaleTransform ScaleX="0.8" ScaleY="0.8"/>
</Setter.Value>
</Setter>
</Style>
Usage
<Border Background="Red" Style="{StaticResource Shrink80pcBorder}">
<Your Item/Content/>
</Border>

Adding line to a shape in XAML

I am modifying the button visual appearance in my XAML code with a hexagon. Now, I want to add 2 lines to the two outer edges of the hexagon like the image below:
https://skydrive.live.com/redir.aspx?cid=204df65b0e6e1655&resid=204DF65B0E6E1655!117&parid=204DF65B0E6E1655!107&authkey=!AEzKZRmwMNhBWxM
Can anyone tell how and where to add it ? My code is something like this
<Page.Resources>
<Style TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Canvas>
<Polygon Canvas.Top="30" Points=
"430,0
400,32
-30,32
-60,0
-30,-32
400,-32"
Stroke="Brown" StrokeThickness="10"/>
<ContentPresenter Canvas.Left="80" Foreground="White" FontSize="40"></ContentPresenter>
</Canvas>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Page.Resources>
<Grid Background="Black">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Button Grid.Row="1" Margin="40,-100 0,-50" HorizontalAlignment="Center">Hello World</Button>
</Grid>
I cant get the line to connect to those edges and spread all the way to the page end.
Any idea ?
Do you want this within your button style? I was able to achieve this through the XAML button control template code below.
I put separators in a grid and then put rectangles on top them to add stroke to the image.
I also added an upper margin of 2 onto the polygon to align with the rectangles.
<ControlTemplate TargetType="Button">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="500"/>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Rectangle Fill="White" Grid.Column="0"/>
<Rectangle Fill="White" Grid.Column="2"/>
<Separator Background="White" Grid.Column="0"/>
<Separator Background="White" Grid.Column="2"/>
<Canvas Grid.Column="1" Margin="64,2,0,0">
<Polygon Points=
"430,0
400,32
-30,32
-60,0
-30,-32
400,-32"
Stroke="Brown" StrokeThickness="10"/>
<ContentPresenter Canvas.Left="80" Foreground="White" FontSize="40"/>
</Canvas>
</Grid>
</ControlTemplate>

WPF multi-line TabControl without rearranging rows

The WPF TabControl with its default TabPanel arranges tab items into multiple rows when the horizontal size is too small. Then the tab selection changes the order of these rows, so the selected tab item is always in the first row.
I found several articles on how to replace TabPanel with another items control so instead of the multiline behavior they get scrolling tabs.
I would like to keep the multiple rows (no scrolling), but disable the rearrangement of rows. Once the tabs are created, they should stay in position, no matter how the selection changes. Is this possible?
have you tried overriding the default style with something like this? ie: using a wrappanel instead of a TabPanel?
<Style x:Key="{x:Type TabControl}" TargetType="{x:Type TabControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabControl}">
<Grid TabNavigation="Local" SnapsToDevicePixels="true" ClipToBounds="true">
<Grid.ColumnDefinitions>
<ColumnDefinition Name="ColumnDefinition0" />
<ColumnDefinition Name="ColumnDefinition1" Width="0" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Name="RowDefinition0" Height="Auto" />
<RowDefinition Name="RowDefinition1" Height="*" />
</Grid.RowDefinitions>
<WrapPanel Name="HeaderPanel" ZIndex="1" TabIndex="1" Column="0" Row="0" Margin="2,2,2,0" IsItemsHost="true" />
<Border Name="ContentPanel" Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}" TabNavigation="Local" DirectionalNavigation="Contained" TabIndex="2" Column="0" Row="1">
<ContentPresenter Name="PART_SelectedContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" Margin="{TemplateBinding Padding}" ContentSource="SelectedContent" />
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The only solution I found was modifying the framework's TabPanel class so that its int GetActiveRow(int[] solution) method always returns 0. Although this solves the problem, I'm not sure it is legal to use the framework's source in this way.
I think vigoo's answer is incomplete. int GetActiveRow(int[] solution) is a private method for the TabPanel class inside of the System.Windows.Controls.Primitives namespace. So you must create a copy of the TabPanel class from the WPF source code (which is available at WPF source github and place it in a new namespace.
// Returns the row which contain the child with IsSelected==true
private int GetActiveRow(int[] solution)
{
// Prevent Tabs from re-ordering when selecting a tab
return 0;
/*int activeRow = 0;
int childIndex = 0;
if (solution.Length > 0)
{
foreach (UIElement child in InternalChildren)
{
if (child.Visibility == Visibility.Collapsed)
continue;
bool isActiveTab = (bool)child.GetValue(Selector.IsSelectedProperty);
if (isActiveTab)
{
return activeRow;
}
if (activeRow < solution.Length && solution[activeRow] == childIndex)
{
activeRow++;
}
childIndex++;
}
}
// If the is no selected element and aligment is Top - then the active row is the last row
if (TabStripPlacement == Dock.Top)
{
activeRow = _numRows - 1;
}
return activeRow;*/
}
Then create a template for the TabControl and reference your new TabPanel in the Template (I called it overrides:TabPanel here). Don't forget to add a reference to the new TabPanel class in your ResourceDictionary (or wherever you defined the new style) xmlns:overrides="clr-namespace:MyNamespace.WPF.Overrides".
<Style x:Key="staticTabs"
TargetType="{x:Type TabControl}">
<Setter Property="Padding" Value="2" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="Background" Value="{StaticResource TabItem.Selected.Background}" />
<Setter Property="BorderBrush" Value="{StaticResource TabItem.Selected.Border}" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabControl}">
<Grid x:Name="templateRoot"
ClipToBounds="true"
KeyboardNavigation.TabNavigation="Local"
SnapsToDevicePixels="true">
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="ColumnDefinition0" />
<ColumnDefinition x:Name="ColumnDefinition1"
Width="0" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition x:Name="RowDefinition0"
Height="Auto" />
<RowDefinition x:Name="RowDefinition1"
Height="*" />
</Grid.RowDefinitions>
<overrides:TabPanel x:Name="headerPanel"
Grid.Row="0"
Grid.Column="0"
Margin="2,2,2,0"
Panel.ZIndex="1"
Background="Transparent"
Grid.IsSharedSizeScope="True"
IsItemsHost="true"
KeyboardNavigation.TabIndex="1" />
<Border x:Name="contentPanel"
Grid.Row="1"
Grid.Column="0"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
KeyboardNavigation.DirectionalNavigation="Contained"
KeyboardNavigation.TabIndex="2"
KeyboardNavigation.TabNavigation="Local">
<ContentPresenter x:Name="PART_SelectedContentHost"
Margin="{TemplateBinding Padding}"
ContentSource="SelectedContent"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Finally your Tab control will reference this new Template:
<TabControl Style="{StaticResource staticTabs}" />

How to create a bordered table in Silverlight?

I am currently using Silverlight 3. I want to create the equivalent of a 2x2 HTML table. I want each cell to have a black border. How do I do this in Silverlight? Isn't there a property I can set on a Grid element to make each cell have a border?
Nope. Grid is simply one of a number of panel types that are designed to layout their children in specific way. Grids are used extensively in many different and often nested ways. They are lightweight and therefore do not carry loads of baggage that may or may not get used, such as in this a bunch of properties to determine borders on "cells".
To create a border on each cell simply use the Border control:
<Grid>
<Grid.Resources>
<Style x:Key="borderStyle" TargetType="Border">
<Setter Property="BorderBrush" Value="Black" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Padding" Value="2" />
</Style>
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Border Style="{StaticResource borderStyle}" Grid.Row="0" Grid.Column="0">
<!-- Cell 0.0 content here -->
</Border>
<Border Style="{StaticResource borderStyle}" Grid.Row="0" Grid.Column="1">
<!-- Cell 0.1 content here -->
</Border>
<Border Style="{StaticResource borderStyle}" Grid.Row="1" Grid.Column="0">
<!-- Cell 1.0 content here -->
</Border>
<Border Style="{StaticResource borderStyle}" Grid.Row="1" Grid.Column="1">
<!-- Cell 1.1 content here -->
</Border>
</Grid>

Resources