Update source with TemplateBinding - wpf

I use this style for all my labels
<Style TargetType="Label" x:Key="LabelStyle">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Label">
<StackPanel Orientation="Horizontal" >
<TextBox Loaded="MyTextBlock_Loaded" x:Name="EditControl" Visibility="Collapsed" Text="{TemplateBinding Tag}" />
<Label Content="{TemplateBinding Content}" Grid.Column="1" Grid.Row="1">
</Label>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
and my sample label
<Label Grid.Column="0" Grid.Row="0" Content="Photo" Style="{StaticResource LabelStyle}" Tag="{Binding fieldsCode.firstName, UpdateSourceTrigger=PropertyChanged}"/>
But I feel that TemplateBiding doesn't support update of property. How can solve this issue

Try this for two-way binding
Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Tag, Mode=TwoWay}"

If you want a one-way binding from within the ControlTemplate to a property of its templated parent, use {TemplateBinding}. For all other scenarios use {Binding} instead:
<TextBox Loaded="MyTextBlock_Loaded" x:Name="EditControl" Visibility="Collapsed" Text="{Binding Tag, Mode=TwoWay}" />

Related

Create a Style for TabItem in WPF

I want to show an image and Text on each and every tabItem of my TabControl.
So, I created a Style as follows:
<TabControl.Resources>
<Style TargetType="TabItem">
<Style.Setters>
<Setter Property="Header">
<Setter.Value>
<StackPanel Orientation="Horizontal" Background="#FF2A2A2A" Margin="-7,-2" Cursor="Hand">
<Image Source="{Binding Tag}" Margin="10"/>
<TextBlock Text="{Binding Content}" FontSize="32" Foreground="White" Margin="0,10,10,10"/>
</StackPanel>
</Setter.Value>
</Setter>
</Style.Setters>
</Style>
</TabControl.Resources>
Now in the TabItem:
<TabItem Tag="Images/Plus.png" Content="Create New" />
But I don't see any header on any tabItems??????
You need to use RelativeSource to travel up Visual tree to get your property bindings to work. By default it will search for property in DataContext of Image and not on TabItem.
<Image Source="{Binding Tag, RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType=TabItem}}" Margin="10"/>
and similarly for TextBlock:
<TextBlock Text="{Binding Content, RelativeSource={RelativeSource
Mode=FindAncestor, AncestorType=TabItem}}"
FontSize="32" Foreground="White" Margin="0,10,10,10"/>
specify the name of the style
<TabControl.Resources>
<Style x:Key="TabItemStyle" TargetType="{x:Type TabItem}">
<Style.Setters>
and indicate style in TabItem
<TabItem Tag="Images/Plus.png" Content="Create New" Style="{StaticResource TabItemStyle}" />

ItemContainerStyle reuse silverlight 5

I have control template with a checkbox as this:
<Style x:Key="GeneralChkbxItemStyle" TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Grid x:Name="RootElement">
<CheckBox ClickMode="Press" Content="{Binding Path=Name}"
IsChecked="{Binding Path=IsSelected, Mode=TwoWay}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter
</Style>
I use this in a combobox and a listbox mentioning like this ItemContainerStyle="{StaticResource GeneralChkbxItemStyle .It works perfect when the datasource has a property named Name .
But I am wondering how can I use this template with other data source having class which does not have a name property . It might have a property name2, or name 3 etc depending on the datasource.
Any suggestions? Thanks.
In your template:
<CheckBox ClickMode="Press"
Content="{TemplateBinding Content}"
ContentTemplate="{templateBinding ContentTemplate}"
IsChecked="{Binding Path=IsSelected, Mode=TwoWay}" />
Then in your view:
<ListBox DisplayMemberPath="Name"..../>
<!--OR-->
<ListBox DisplayMemberPath="Name2"..../>
<!--OR-->
......
You may use implicit data templates.
<DataTemplate DataType="MyApp:Person">
<TextBlock Text="{Binding Name}" />
</DataTemplate>
<DataTemplate DataType="MyApp:Booking">
<TextBlock Text="{Binding Id}" />
</DataTemplate>
<Style x:Key="GeneralChkbxItemStyle"
TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Grid x:Name="RootElement">
<CheckBox ClickMode="Press"
Content="{Binding .}"
IsChecked="{Binding Path=IsSelected, Mode=TwoWay}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Bind image in templated ListBox to ViewModel property

TL;DR - I had a binding error. Tired eyes miss things.
I have implemented a multi-select CheckBox list using a ListBox as the container. Now, beside each checkbox in the list I want to display an image whose visbility is bound to a ViewModel property, but I'm having difficulty doing this.
My styles are:
<Grid.Resources>
<Style x:Key="ListBoxCheckStyle" TargetType="ListBox">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBox">
<ItemsPresenter HorizontalAlignment="Left" VerticalAlignment="Top"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<ItemsPanelTemplate x:Key="ListBoxCheckStyleItemsPanelTemplate">
<StackPanel />
</ItemsPanelTemplate>
<Style x:Key="ListBoxItemCheckStyle" TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<StackPanel Orientation="Horizontal">
<ChimeControls:CheckBox
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
Margin="0,0,10,0"
IsChecked="{Binding IsSelected, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"/>
<Image
Width="16"
Height="16"
VerticalAlignment="Center"
Source="{StaticResource OccurredStatusTypeImageSource}"
Visibility="{Binding HasConsentCondition, Converter={StaticResource BoolToVisibilityConverter}, FallbackValue=Collapsed}"
HorizontalAlignment="Right"
Margin="10,0,10,0" />
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
My Listbox is defined as:
<ListBox
x:Name="objectivesListBox"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Style="{StaticResource ListBoxCheckStyle}"
ItemsPanel="{StaticResource ListBoxCheckStyleItemsPanelTemplate}"
ItemContainerStyle="{StaticResource ListBoxItemCheckStyle}"
ItemsSource="{Binding ObjectivesList}"
DisplayMemberPath="mgt_plan_obj_name"
AttachedProperties:ListBoxSelectedItems.Items="{Binding SelectedObjectives, Mode=TwoWay}"
SelectionMode="Multiple"/>
My image never displays though, and the getter of the property the Visibility is bound to is never called. What am I missing?
As suggested by nemesv, I checked my output window again and there was my binding error.

How to expand bound & styled TreeViewItem nodes

I have a TreeView in WPF which I have bound to a collection of categories that itself contains a collection of categories and son on and so forth. Currently, I'm binding the collection successfully and having all of my category names appearing. However, I also have an IsExpanded property on my collection objects that when all set to true only expand the first TreeViewItem but no subsequent ones.
Does anyone know what may be wrong with my TreeView styles?
<HierarchicalDataTemplate x:Key="menuHierarchicalTemplate" ItemsSource="{Binding Path=SubCategories, Mode=TwoWay}" >
<Border x:Name="treeViewItemBorder"
CornerRadius="3"
MinWidth="125"
BorderBrush="Silver" Background="Transparent">
<StackPanel Orientation="Horizontal" >
<TextBlock Height="24" Padding="5" Text="{Binding Path=Name}" />
</StackPanel>
</Border>
</HierarchicalDataTemplate>
<Style x:Key="treeViewItemStyle" TargetType="TreeViewItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TreeViewItem">
<TreeViewItem IsExpanded="{Binding Path=IsExpanded, Mode=TwoWay}"
ItemsSource="{Binding Path=SubCategories}"
ItemTemplate="{StaticResource menuHierarchicalTemplate}" >
<TreeViewItem.Header>
<StackPanel Orientation="Horizontal" >
<TextBlock Height="24" FontSize="12" Padding="5" Text="{Binding Path=Name}" />
</StackPanel>
</TreeViewItem.Header>
</TreeViewItem>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<TreeView Name="menuTreeView"
Background="Transparent"
BorderBrush="Transparent"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
Margin="10"
ItemContainerStyle="{StaticResource treeViewItemStyle}">
</TreeView>
Thanks,
Xam
You are applying the "treeViewItemStyle" only to the first level of items in the TreeView. You have to set it as well as the ItemContainerStyle of the TreeViewItems. So, in your ControlTemplate, you'll need something like:
<ControlTemplate TargetType="TreeViewItem">
<TreeViewItem ItemContainerStyle="{StaticResource treeViewItemStyle}".../>
</ControlTemplate>
Better yet, you can just remove the "x:Key" attribute in your Style declaration. Doing so will automatically apply the style to all TreeViewItems.
SIDE NOTE:
I would suggest that instead of overriding the ControlTemplate like what you did above, just use property Setters in the Style instead. Something like:
<Style TargetType="TreeViewItem">
<Setter Property="IsExpanded" Value="{Binding Path=IsExpanded, Mode=TwoWay}"/>
<Setter Property="ItemsSource" Value="{Binding Path=SubCategories}"/>
<Setter Property="ItemTemplate" Value="{StaticResource menuHierarchicalTemplate}"/>
<Setter Property="Header">
<Setter.Value>
<StackPanel Orientation="Horizontal" >
<TextBlock Height="24" FontSize="12" Padding="5" Text="{Binding Path=Name}" />
</StackPanel>
</Setter.Value>
</Setter>
</Style>
It's quite unusual to use the same Control as part of the ControlTemplate of itself (i.e. using TreeViewItem in the ControlTemplate of a TreeViewItem).

Setting tooltip to equal content

I'm trying to set a data grid's cell's tooltip to be equal to the text inside of a TextBlock in that cell. What I have so far is this:
<Style x:Key="CellStyle" TargetType="{x:Type DataGridCell}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="DataGridCell">
<Grid>
<TextBlock Margin="2" VerticalAlignment="Center"
HorizontalAlignment="Left" TextWrapping="Wrap" >
<ContentPresenter Content="{TemplateBinding Property=ContentControl.Content}" />
<TextBlock.ToolTip>
<ContentPresenter Content="{TemplateBinding Property=ContentControl.Content}" />
</TextBlock.ToolTip>
</TextBlock>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
However, what this does is very briefly show the tooltip and then the content in the cell is removed, so nothing shows up at all. Also, setting the tooltip from outside the Template setter is an option, but I'm not sure what the corrent binding is to do that.
My example here is for a simple label but this can be applied to other controls.
<Label Name="lblFormName" Content="Form Elements:" FontWeight="Bold" HorizontalAlignment="Left" Width="295" >
<Label.ToolTip>
<Binding ElementName="lblFormName" Path="Content"/>
</Label.ToolTip>
</Label>
Check out this link: http://msdn.microsoft.com/en-us/library/ms742167.aspx
or this link for a bunch of binding "how-to"s from MS http://msdn.microsoft.com/en-us/library/ms752039.aspx
Have you tried using RelativeSource? I heard of some issues about TemplateBinding vs. RelativeSource (WPF TemplateBinding vs RelativeSource TemplatedParent).
<ContentPresenter Content="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type YourAncestorType}, AncestorLevel=1},Path=Content}" />
Where "YourAncestorType" is the type of the parent you want to find.
Or you could also try the same approach with
<ContentPresenter Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content}" />
See also: http://www.wpfwiki.com/Default.aspx?Page=WPF%20Q5.3&AspxAutoDetectCookieSupport=1
Try removing the ToolTip from the ControlTemplate and defining a separate Setter in the Style for the Tooltip.
Here is the XAML using your sample:
<Style x:Key="CellStyle" TargetType="{x:Type WpfToolkit:DataGridCell}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="WpfToolkit:DataGridCell">
<Grid>
<TextBlock Margin="2" VerticalAlignment="Center"
HorizontalAlignment="Left" TextWrapping="Wrap" >
<ContentPresenter Content="{TemplateBinding Property=ContentControl.Content}" />
<!--<TextBlock.ToolTip>
<ContentPresenter Content="{TemplateBinding Property=ContentControl.Content}" />
</TextBlock.ToolTip>-->
</TextBlock>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=Content.Text}"/>
</Style>

Resources