Inheriting / BasedOn datatemplate - wpf

I have a DataTemplate that I am using within my WPF application -
<DataTemplate x:Key="mattersTemplate">
<Border Name="border" BorderBrush="Aqua" BorderThickness="1" Padding="5" Margin="5">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="FileRef:"/>
<TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding Path=FileRef}" />
<TextBlock Grid.Row="1" Grid.Column="0" Text="Description:"/>
<TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding Path=Description}"/>
<TextBlock Grid.Row="2" Grid.Column="0" Text="Priority:"/>
<TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding Path=Priority}"/>
</Grid>
</Border>
</DataTemplate>
I then (in a DocumentSetTemplateSelector class) define which template to use;
What I would like to do / know is;
Create 4 other templates that would inherit this above template AND then allow certain attributes to be over-written;
An example (this template inherits from the above class) - so they look the same;
<DataTemplate x:Key="documentSet_Accounting">
<ContentPresenter Content="{Binding mattersTemplate}"
ContentTemplate="{StaticResource mattersTemplate}">
</ContentPresenter>
</DataTemplate>
I would like for there to be a style attached to this (if possible) so to get this effect;
<DataTemplate x:Key="documentSet_Accounting">
<ContentPresenter fontsize="20" Content="{Binding mattersTemplate}"
ContentTemplate="{StaticResource mattersTemplate}">
</ContentPresenter>
</DataTemplate>
or
<DataTemplate x:Key="documentSet_Accounting">
<ContentPresenter Style="AccountingStyle" Content="{Binding mattersTemplate}"
ContentTemplate="{StaticResource mattersTemplate}">
</ContentPresenter>
</DataTemplate>

How about using style inheritance within the templates rather than template inheritance?
<Style x:Key="mattersTemplateStyle">
<Setter Property="TextBlock.Foreground" Value="Green"/>
</Style>
<Style x:Key="documentSet_AccountingStyle" BasedOn="{StaticResource mattersTemplateStyle}">
<Setter Property="TextBlock.FontSize" Value="20"/>
</Style>
<DataTemplate x:Key="mattersTemplate">
<Border Name="border" BorderBrush="Aqua" BorderThickness="1" Padding="5" Margin="5">
<Grid Style="{StaticResource mattersTemplateStyle}">
[...]
</Grid>
</Border>
</DataTemplate>
<DataTemplate x:Key="documentSet_Accounting">
<Grid Style="{StaticResource documentSet_AccountingStyle}">
<ContentPresenter Content="{Binding mattersTemplate}" ContentTemplate="{StaticResource mattersTemplate}"></ContentPresenter>
</Grid>
</DataTemplate>

Related

WPF double line on the top of listbox

I am new to wpf. I need to have a window that list all accounts added. But my application shows a double line below the "Accounts". Not sure what caused this. could someHow to fix this? Here is my xaml
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<StackPanel x:Name="StackPanel1" Grid.Row="0" HorizontalAlignment="Left" Height="150" VerticalAlignment="Top" Width="444">
<TextBlock x:Name="AddAccountTextBlock" HorizontalAlignment="Left" TextWrapping="Wrap" VerticalAlignment="Top" Height="60" Width="369" Text="Add account to allow for simple access to your company resources
" SnapsToDevicePixels="True"/>
<Button x:Name="AddAccount" Content="Add Account" HorizontalAlignment="Left" VerticalAlignment="Top" Width="140" RenderTransformOrigin="0.466,0.977" IsCancel="True" Height="40" Foreground="White" Background="Blue" Click="OnAddAccount"/>
</StackPanel>
<StackPanel x:Name="StackPanel2" Grid.Row="2" HorizontalAlignment="Left" Height="154" Width="444">
<TextBlock x:Name="AccountsTextBlock" TextWrapping="Wrap" Text="Accounts" Height="25" Width="68" FontSize="16" FontFamily="Tahoma"/>
<ListBox x:Name="accounts" Height="130" VerticalAlignment="Top">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Height" Value="100"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border Name="_Border" BorderBrush="Gray" BorderThickness="0.5" SnapsToDevicePixels="true">
<ContentPresenter />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter TargetName="_Border" Property="Background" Value="LightSkyBlue"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image HorizontalAlignment="Left" VerticalAlignment="Center" Grid.Row="0" Grid.Column="0" Width="100" Source="{Binding Path=imagePath}" />
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Row="0" Grid.Column="1" Text="{Binding Path=userInfo}"></TextBlock>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</Grid>
You may remove the borders of the ListBox by setting the BorderThickness property:
<ListBox x:Name="accounts" Height="130" VerticalAlignment="Top" Margin="100"
BorderThickness="0">
You may set it to 1,0,1,0 to remove only the top and bottom borders. The order is left, top, right, bottom.

Binding within a ListView GroupStyle Header

I use a ListView.GroupStyle in conjunction with a HeaderTemplate to style ListView Headers.
<ListView.GroupStyle>
<GroupStyle HeaderTemplate="{StaticResource headerTemplate}" />
</ListView.GroupStyle>
...
<DataTemplate x:Key="headerTemplate">
<Border Opacity=".9" Padding="0,5,0,5" Margin="0" BorderThickness="0" BorderBrush="LightGray" HorizontalAlignment="Stretch" Background="#ffffff">
<Grid Margin="3" HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="3*"/>
</Grid.ColumnDefinitions>
<TextBlock
Grid.Column="0"
Text="{Binding Path=Name}"
HorizontalAlignment="Right"/>
<StackPanel Grid.Column="1" Orientation="Horizontal">
<Button Margin="5" Padding="5"
HorizontalAlignment="left"
Content="{Binding ???}"
Command="{Binding ???}" />
</StackPanel>
</Grid>
</Border>
</DataTemplate>
Now I would like to put controls in that headerTemplate - e.g. a Button to execute actions to all entries within that group. How do I do this? How is Binding done within a GroupStyle HeaderTemplate?
You can use a RelativeSource Binding to access the DataContext of the GridView from the HeaderTemplate:
<DataTemplate x:Key="headerTemplate">
<Border Opacity=".9" Padding="0,5,0,5" ...>
<Grid Margin="3" HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="3*"/>
</Grid.ColumnDefinitions>
<TextBlock
Grid.Column="0"
Text="{Binding Name}"
HorizontalAlignment="Right"/>
<StackPanel Grid.Column="1" Orientation="Horizontal">
<Button Margin="5" Padding="5"
HorizontalAlignment="left"
Content="{Binding DataContext.SomeProperty, RelativeSource={
RelativeSource AncestorType={x:Type GridView}}}"
Command="{Binding DataContext.AnotherProperty, RelativeSource={
RelativeSource AncestorType={x:Type GridView}}}" />
</StackPanel>
</Grid>
</Border>
</DataTemplate>

LabeledPieChart: Style overrides DataTemplate

I have customized the template of LabeledPieChart (source: Bea) in a Style. Then I created a DataTemplate for the Slices of the LabeledPieChart. Both the style and the DataTemplate works great if they are alone. If they are together the Style overrides the DataTemplate that he has no effect. Is it possible to combine these two?
Here is my Code (The Style and the DataTemplate are in Window.Resources):
Style:
<Style TargetType="customControls:LabeledPieChart" >
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="customControls:LabeledPieChart">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="15*" />
<ColumnDefinition Width="9*" />
</Grid.ColumnDefinitions>
<Grid Grid.Column="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<dataVis:Title Content="{TemplateBinding Title}" Style="{TemplateBinding TitleStyle}" Margin="0,5,0,3"/>
<Grid Grid.Row="1" Margin="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<chartPrmtvs:EdgePanel x:Name="ChartArea" Style="{TemplateBinding ChartAreaStyle}">
<Grid Canvas.ZIndex="-1" Background="Transparent" />
<Border Canvas.ZIndex="10" BorderBrush="#FF919191" BorderThickness="0" />
</chartPrmtvs:EdgePanel>
</Grid>
</Grid>
<dataVis:Legend x:Name="Legend" Style="{TemplateBinding LegendStyle}" Title="{TemplateBinding LegendTitle}"
BorderThickness="0" Background="Transparent" FontSize="15" Grid.Column="1"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
DataTemplate:
<DataTemplate DataType="{x:Type local:City}" >
<Border BorderThickness="1" BorderBrush="Gray">
<StackPanel Background="White" Orientation="Horizontal">
<TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type customControls:PieChartLabel}}, Path=FormattedRatio}" VerticalAlignment="Center" Margin="5,0,5,0" />
<TextBlock Text="- " />
<TextBlock Text="{Binding Path=Population}" Margin="5,0,5,0" />
<TextBlock Text="- " />
<TextBlock Text="{Binding Name}" Margin="0,0,5,0"/>
</StackPanel>
</Border>
</DataTemplate>
LabeldPieChart:
<Grid>
<customControls:LabeledPieChart
x:Name="labeledPieChart"
Title="Population of Puget Sound Cities"
Height="500" Width="700"
Grid.Row="3"
BorderBrush="Gray"
>
<customControls:LabeledPieChart.Series>
<customControls:LabeledPieSeries
x:Name="labeledPieSeries"
ItemsSource="{Binding}"
IndependentValuePath="Name"
DependentValuePath="Population"
IsSelectionEnabled="True"
LabelDisplayMode="Auto"
/>
</customControls:LabeledPieChart.Series>
</customControls:LabeledPieChart>
</Grid>

Setting Datacontext on contentpresenter: Binding inside ContentTemplate is not working

I'm learning WPF and the MVVM Pattern and I'm trying to build a calendar-like view.
So I currently have a Grid with 6 rows and 7 columns.
The first row should be the Header, thus specifying the Week days like 'Monday, Tuesday, etc...'
I have the following right now in my MonthView.xaml
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="{Binding RowHeight}"/>
<RowDefinition Height="{Binding RowHeight}"/>
<RowDefinition Height="{Binding RowHeight}"/>
<RowDefinition Height="{Binding RowHeight}"/>
<RowDefinition Height="{Binding RowHeight}"/>
<RowDefinition Height="{Binding RowHeight}"/>
<RowDefinition Height="{Binding RowHeight}"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="{Binding CellWidth}"/>
<ColumnDefinition Width="{Binding CellWidth}"/>
<ColumnDefinition Width="{Binding CellWidth}"/>
<ColumnDefinition Width="{Binding CellWidth}"/>
<ColumnDefinition Width="{Binding CellWidth}"/>
<ColumnDefinition Width="{Binding CellWidth}"/>
<ColumnDefinition Width="{Binding CellWidth}"/>
</Grid.ColumnDefinitions>
<!-- Header Row-->
<ContentPresenter Grid.Row="0" Grid.Column="0">
<ContentPresenter.ContentTemplate>
<DataTemplate>
<TextBlock Text="{Binding DaysOfWeek[0]}"/>
</DataTemplate>
</ContentPresenter.ContentTemplate>
</ContentPresenter>
<ContentPresenter ContentTemplate="{StaticResource CalendarHeaderCellTemplate}" Grid.Row="0" Grid.Column="1" DataContext="{Binding DaysOfWeek[1]}"/>
<ContentPresenter ContentTemplate="{StaticResource CalendarHeaderCellTemplate}" Grid.Row="0" Grid.Column="2" DataContext="{Binding DaysOfWeek[2]}"/>
<ContentPresenter ContentTemplate="{StaticResource CalendarHeaderCellTemplate}" Grid.Row="0" Grid.Column="3" DataContext="{Binding DaysOfWeek[3]}"/>
<ContentPresenter ContentTemplate="{StaticResource CalendarHeaderCellTemplate}" Grid.Row="0" Grid.Column="4" DataContext="{Binding DaysOfWeek[4]}"/>
<ContentPresenter ContentTemplate="{StaticResource CalendarHeaderCellTemplate}" Grid.Row="0" Grid.Column="5" DataContext="{Binding DaysOfWeek[5]}"/>
<ContentPresenter ContentTemplate="{StaticResource CalendarHeaderCellTemplate}" Grid.Row="0" Grid.Column="6" DataContext="{Binding DaysOfWeek[6]}"/>
<!-- 1st Row-->
<ContentPresenter ContentTemplate="{StaticResource CalendarCellTemplate}" Grid.Row="1" Grid.Column="0"/>
<ContentPresenter ContentTemplate="{StaticResource CalendarCellTemplate}" Grid.Row="1" Grid.Column="1"/>
<ContentPresenter ContentTemplate="{StaticResource CalendarCellTemplate}" Grid.Row="1" Grid.Column="2"/>
<ContentPresenter ContentTemplate="{StaticResource CalendarCellTemplate}" Grid.Row="1" Grid.Column="3"/>
<ContentPresenter ContentTemplate="{StaticResource CalendarCellTemplate}" Grid.Row="1" Grid.Column="4"/>
<ContentPresenter ContentTemplate="{StaticResource CalendarCellTemplate}" Grid.Row="1" Grid.Column="5"/>
<ContentPresenter ContentTemplate="{StaticResource CalendarCellTemplate}" Grid.Row="1" Grid.Column="6"/>
On so on: You see the pattern I guess.
Here's the CalendarHeaderCellTemplate
<DataTemplate x:Key="CalendarHeaderCellTemplate">
<StackPanel Margin="5" Background="Blue">
<TextBlock Text="{Binding}"></TextBlock>
</StackPanel>
</DataTemplate>
And here's the important parts of the ViewModel:
public ObservableCollection<string> DaysOfWeek { get; private set; }
public MonthViewModel()
{
this.DaysOfWeek = new ObservableCollection<string> {DayOfWeek.Monday.ToString(), DayOfWeek.Tuesday.ToString(), DayOfWeek.Wednesday.ToString(),
DayOfWeek.Thursday.ToString(), DayOfWeek.Friday.ToString(), DayOfWeek.Saturday.ToString(), DayOfWeek.Sunday.ToString()};
}
Now neither the Contentpresenter where I define the DataTemplate 'inline' does display anything inside its TextBlock nor the CalendarHeaderCellTemplate.
Funny thing is, inside the Visual Studio designer, everything show up correctly, except for the first cell (i.e. the one with the inline template)
Does anyone have a suggestion.
N.B. The 'inline' template was mostly done for testing purposes.
EDIT:
Doing this (see below) instead of using the ContentPresenter works fine. Maybe I use the ContentPresenter in a wrong manner?
<StackPanel Grid.Row="0" Grid.Column="0">
<TextBlock Text="{Binding DaysOfWeek[0]}"/>
</StackPanel>
The reason I want to use a ContentPresenter is because the DataTemplate for the content of every cell is going to be much more than just a textbox in the end.
Try changing your ContentPresenter to
<ContentPresenter Content="{Binding DaysOfWeek[0]}" Grid.Row="0" Grid.Column="0">
<ContentPresenter.ContentTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"/>
</DataTemplate>
</ContentPresenter.ContentTemplate>
</ContentPresenter>
or
<ContentPresenter Content="{Binding}" Grid.Row="0" Grid.Column="0">
<ContentPresenter.ContentTemplate>
<DataTemplate>
<TextBlock Text="{Binding DaysOfWeek[0]}"/>
</DataTemplate>
</ContentPresenter.ContentTemplate>
</ContentPresenter>
and also replace your DataContext with Content like
<ContentPresenter ContentTemplate="{StaticResource CalendarHeaderCellTemplate}" Grid.Row="0" Grid.Column="1" Content="{Binding DaysOfWeek[1]}"/>
try using ContentControl rather than ContentPresenter
<Style x:Key="CalendarCell" TargetType="ContentControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ContentControl">
<StackPanel Margin="5" Background="{TemplateBinding Background}">
<TextBlock Text="{TemplateBinding Content}"
Foreground="{TemplateBinding Foreground}" />
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Header Row-->
<ContentControl Style="{StaticResource CalendarCell}"
Content="{Binding DaysOfWeek[0]}"
Background="Blue"
Foreground="White" />
<ContentControl Style="{StaticResource CalendarCell}"
Content="{Binding DaysOfWeek[1]}"
Background="Blue"
Foreground="White"
Grid.Column="1" />
<ContentControl Style="{StaticResource CalendarCell}"
Content="{Binding DaysOfWeek[2]}"
Background="Blue"
Foreground="White"
Grid.Column="2" />
<ContentControl Style="{StaticResource CalendarCell}"
Content="{Binding DaysOfWeek[3]}"
Background="Blue"
Foreground="White"
Grid.Column="3" />
<ContentControl Style="{StaticResource CalendarCell}"
Content="{Binding DaysOfWeek[4]}"
Background="Blue"
Foreground="White"
Grid.Column="4" />
<ContentControl Style="{StaticResource CalendarCell}"
Content="{Binding DaysOfWeek[5]}"
Background="Blue"
Foreground="White"
Grid.Column="5" />
<ContentControl Style="{StaticResource CalendarCell}"
Content="{Binding DaysOfWeek[6]}"
Background="Blue"
Foreground="White"
Grid.Column="6" />
<!-- 1st Row-->
<ContentControl Style="{StaticResource CalendarCell}"
Content=""
Background="Wheat"
Foreground="Black"
Grid.Row="1" />
<ContentControl Style="{StaticResource CalendarCell}"
Content=""
Background="Wheat"
Foreground="Black"
Grid.Column="1"
Grid.Row="1" />
<ContentControl Style="{StaticResource CalendarCell}"
Content=""
Background="Wheat"
Foreground="Black"
Grid.Column="2"
Grid.Row="1" />
<ContentControl Style="{StaticResource CalendarCell}"
Content=""
Background="Wheat"
Foreground="Black"
Grid.Column="3"
Grid.Row="1" />
<ContentControl Style="{StaticResource CalendarCell}"
Content=""
Background="Wheat"
Foreground="Black"
Grid.Column="4"
Grid.Row="1" />
<ContentControl Style="{StaticResource CalendarCell}"
Content=""
Background="Wheat"
Foreground="Black"
Grid.Column="5"
Grid.Row="1" />
<ContentControl Style="{StaticResource CalendarCell}"
Content=""
Background="Wheat"
Foreground="Black"
Grid.Column="6"
Grid.Row="1" />

What wrong with this Template

I am using DataTrigger to change the DataTemplate based on a enum.
<TreeView >
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type model:Card}" ItemsSource="{Binding Reqs}">
<StackPanel VerticalAlignment="Center">
<TextBlock Text="{Binding Label}" FontWeight="Bold" Foreground="Gray" HorizontalAlignment="Stretch" VerticalAlignment="Center" FontSize="15"/>
<TextBlock Text="{Binding Reqs.Count}" FontWeight="UltraLight" Foreground="Gray" HorizontalAlignment="Stretch" VerticalAlignment="Center" FontSize="10"/>
</StackPanel>
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type model:ReqCard}">
<ContentControl>
<ContentControl.Style>
<Style TargetType="{x:Type ContentControl}">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate >
<Border Width="340" Background="LightBlue">
<Grid Name="PGrid" Margin="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Margin="2" Text="{Binding Label}" Foreground="Gray" FontSize="15" FontWeight="Normal"/>
<CheckBox Grid.Column="1" Margin="2" IsChecked="{Binding IsMeet}" Click="IsMeet_OnClick"/>
</Grid>
</Border>
</DataTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding DemandType}" Value="{x:Static enums:DemandType.Condition}">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate >
<Border Width="340" Background="LightBlue" >
<Grid Name="KGrid" Margin="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Margin="2" Text="{Binding Label}" Foreground="Gray" FontSize="15" FontWeight="Normal"/>
<TextBox Grid.Column="1" Width="20" Margin="2" Text="{Binding Condition}" Click="Condition_OnClick"/>
</Grid>
</Border>
</DataTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
</DataTemplate>
</TreeView.Resources>
</TreeView>
It displays no data.

Resources