How to get ContentControl to resolve DataTemplate - wpf

Why does this not resolve the datatemplate?
<Window.Resources>
<DataTemplate DataType="system:DateTime" >
<Grid Background="Aqua">
<TextBlock Text="{Binding Day}"></TextBlock>
</Grid>
</DataTemplate>
</Window.Resources>
<Grid>
<ContentControl Content="{x:Static system:DateTime.Now}"/>
</Grid>
Writing a TemplateSelector feels like an overkill.

DataType design suggests the presence of a directive x:Type like that:
<DataTemplate DataType="{x:Type system:DateTime}">
<Grid Background="Aqua">
<TextBlock Text="{Binding Day}" Height="30" Width="100" HorizontalAlignment="Center" />
</Grid>
</DataTemplate>
See the MSDN for more information.

Related

Reference converter in another xaml

I got a datatemplate in Resource.xaml:
<DataTemplate x:Key="SplitViewMenuItemWithCount">
<RelativePanel>
<RelativePanel RelativePanel.AlignVerticalCenterWithPanel="True" Margin="0,10,0,10">
<SymbolIcon Foreground="White" Width="25" RelativePanel.AlignVerticalCenterWithPanel="True" Symbol="{Binding Symbol}" x:Name="SymbolIcon" Margin="10,0,0,0"/>
<StackPanel Visibility="{Binding Count, Converter={StaticResource BooleanToVisibilityConverter}, TargetNullValue=Collapsed, FallbackValue=Collapsed}" x:Name="StackPanelCount" RelativePanel.RightOf="SymbolIcon" Margin="0,20,0,0" CornerRadius="9" Background="White" Width="15" Height="15">
<TextBlock Text="{Binding Count, FallbackValue='0'}" TextAlignment="Center" FontSize="10" Foreground="{StaticResource AppDarkBlueColor}"/>
</StackPanel>
<TextBlock Margin="10,0,0,0" Foreground="White" x:Name="TextBlockMenuItemText" RelativePanel.RightOf="StackPanelCount" Text="{Binding Text}" FontSize="16" Padding="5,3,0,5"/>
</RelativePanel>
</RelativePanel>
</DataTemplate>
I'm using the datatemplate in my MainPage.xaml as a datatemplate for a ListView, but it crashes because my BooleanToVisibilityConverter. It can't find the converter in Resource.xaml.
However if I put the datatemplate in my MainPage.Resources it finds the converter (because it's defined there).
Is there any way to keep the datatemplate in Resource.xaml? I rather have it there than in MainPage.Resources.
You have to add a reference from your mainPage.xaml to your resources.xaml by using ResourceDictionnary tag as following:
<Window x:Class="MainPage" ... ... >
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/YourProjectDLL;component/Resource.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
... Your window body
</Grid>
</Window>

How to add a button outside datatemplate in itemscontrol

I have created a WPF app.In that I have a Datatemplate as follows
<DataTemplate x:Key="ItemTemplate">
<StackPanel>
<TextBlock Text="item"/>
<TextBlock Text="{Binding Number}"/>
</StackPanel>
</DataTemplate>
I have an ItemsControl like this
<ItemsControl ItemsSource="{Binding Items}"
Grid.Column="1"
Grid.Row="3"
ItemTemplate="{StaticResource ItemTemplateWithButton}" />
where I need a itemtemplate like this
<DataTemplate x:Key="ItemTemplateWithButton">
<StackPanel>
<StackPanel>
<TextBlock Text="item"/>
<TextBlock Text="{Binding Number}"/>
</StackPanel>
<StackPanel>
<Button>
<StackPanel>
<TextBlock Text="item"/>
<TextBlock Text="{Binding Number}"/>
</StackPanel>
</Button>
</StackPanel>
</StackPanel>
</DataTemplate>
Is there any possibility of reusing the datatemplate in the new itemscontrol?
You can use ContentControl too
<DataTemplate x:Key="ItemTemplate">
<StackPanel>
<TextBlock Text="item"/>
<TextBlock Text="{Binding Number}"/>
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="ItemTemplateWithButton">
<StackPanel>
<ContentControl ContentTemplate="{StaticResource ItemTemplate}" />
<Button>
<ContentControl ContentTemplate="{StaticResource ItemTemplate}" />
</Button>
</StackPanel>
</DataTemplate>
What I understand by reading this answer and what Liero mentioned in the comments is it's possible to reuse a DataTemplate by using either ContentPresenter or ContentControl. However:
ContentPresenter is more lightweight.
ContentPresenter is designed to be used inside control templates.
ContnetPresenter is designed to be used as-is while ContentControl is designed to be extended (inherited from).
As a result, here is a solution based on what you asked:
<DataTemplate x:Key="ItemTemplate">
<StackPanel>
<TextBlock Text="item"/>
<TextBlock Text="{Binding Number}"/>
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="ItemTemplateWithButton">
<StackPanel>
<ContentPresenter ContentTemplate="{StaticResource ItemTemplate}"/>
<StackPanel>
<Button Content="{Binding}" ContentTemplate="{StaticResource ItemTemplate}" />
</StackPanel>
</StackPanel>
</DataTemplate>
You could create a UserControl to hold the xaml you want to reuse:
<UserControl x:Class="StackOverflow.SharedControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<StackPanel>
<TextBlock Text="item">
</TextBlock>
<TextBlock Text="{Binding Number}"></TextBlock>
</StackPanel>
</Grid>
</UserControl>
Then use this UserControl in both templates.
<DataTemplate x:Key="ItemTemplate">
<controls:SharedControl/>
</DataTemplate>
<DataTemplate x:Key="ItemTemplateWithButton">
<StackPanel>
<controls:SharedControl/>
<StackPanel>
<Button>
<StackPanel>
<TextBlock Text="item">
</TextBlock>
<TextBlock Text="{Binding Number}"></TextBlock>
</StackPanel>
</Button>
</StackPanel>
</StackPanel>
</DataTemplate>

DataTemplating Binding not correct

I have the following code which Binds to properties within a ToolTip DataTemplate:
<Window x:Class="WpfConcepts.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:telerikGrid="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls.GridView"
xmlns:telerikData="clr-namespace:Telerik.Windows.Data;assembly=Telerik.Windows.Data"
xmlns:telerikGridview="clr-namespace:Telerik.Windows.Controls.GridView;assembly=Telerik.Windows.Controls.GridView"
xmlns:telerikInput="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls.Input" Width="200" Height="480">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<telerikGrid:RadGridView Grid.Column="0" Grid.Row="0" x:Name="FXRateGridView" ItemsSource="{Binding CarList}" ScrollViewer.HorizontalScrollBarVisibility="Visible" ScrollViewer.VerticalScrollBarVisibility="Visible" ColumnWidth="*" MinColumnWidth="50" AutoGenerateColumns="False">
<telerikGrid:RadGridView.Columns>
<telerikGrid:GridViewDataColumn>
<telerikGrid:GridViewDataColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}">
<TextBlock.ToolTip>
<ToolTip>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Path=Colour}"/>
</StackPanel>
</DataTemplate>
</ToolTip>
</TextBlock.ToolTip>
</TextBlock>
</DataTemplate>
</telerikGrid:GridViewDataColumn.CellTemplate>
</telerikGrid:GridViewDataColumn>
</telerikGrid:RadGridView.Columns>
</telerikGrid:RadGridView>
</Grid>
</Window>
The tooltip displays as "System.Window.DataTemplate" which is not the desired effect since I'm expecting the Colour property value instead.
If I don't use a datatemplate within the ToolTip then I get the correct value, I assume my usage DataTemplate is not correct.
If you want to reuse the toolTip create an instance of it in Window Resources and use it wherever you need, using StaticResource like this -
<Window>
....
<Window.Resources>
<ToolTip x:Key="ColourToolTip">
<StackPanel>
<TextBlock Text="{Binding Path=Colour}"/>
</StackPanel>
</ToolTip>
</Window.Resources>
Use this resource in your template like this-
<TextBlock Text="{Binding Name}"
ToolTip="{StaticResource ColourToolTip}">
There is no need for DataTemplate, just use the following:
<ToolTip>
<TextBlock Text="{Binding Path=Colour}"/>
</ToolTip>

How to reuse contents in wpf/mvvm

I have a UI that displays a pattern of "first name/last name". So I thought I would reuse the same template. But I am facing some issues getting the binding right.
Note:-
PrimaryContactDataContext is nothing but a class, with a property named "value" which implements the *INotifyPropertyChanged" interface.
<StackPanel>
<ContentControl DataContext="{Binding Path=PrimaryContactDataContext.Value,Mode=TwoWay}" ContentTemplate="{StaticResource PersonalDetailsTemplate}" />
</StackPanel>
// See the Reusable template below
<UserControl.Resources>
<DataTemplate x:Key="PersonalDetailsTemplate" >
<StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Width="30" Text="Name"></TextBlock>
<TextBox Width="110" Text="{Binding LastName}" IsReadOnly="True"></TextBox>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Width="30" Text="Title"></TextBlock>
<TextBox Width="110" Text="{Binding firstName}" IsReadOnly="True"></TextBox>
</StackPanel>
</StackPanel>
</DataTemplate>
</UserControl.Resources>
Set the Content of the ContentControl, not its DataContext:
<ContentControl Content="{Binding Path=PrimaryContactDataContext.Value,Mode=TwoWay}" ContentTemplate="{StaticResource PersonalDetailsTemplate}" />

WPF Binding: How to databind to Grid?

I have created a class Account.
Next, I have created another class ReorderWindowController which has a field/property SelectedAccount of type Account.
Finally, I have written ReorderWindow WPF window xaml file:
<Window ...
<Window.Resources>
<contollers:ReorderWindowController x:Key="WindowController" />
<DataTemplate DataType="{x:Type entities:Account}">
<Grid Width="140" Height="50" Margin="5">
<TextBlock Text="Some awesome text" />
<TextBlock Text="{Binding Name}" />
<TextBlock Text="Even more awesome text" />
</Grid>
</DataTemplate>
</Window.Resources>
<Grid>
<Grid
Name="AccountGrid"
DataContext="{Binding Source={StaticResource ResourceKey=WindowController},
Path=SelectedAccount}">
</Grid>
</Grid>
</Window>
When I run my code, AccountGrid is not showing anything. Why? How do I make object data bind to the Grid and how do I make it use my data template? Thanks.
Instead of a Grid use a ContentPresenter like this:
<Grid>
<ContentPresenter
Name="AccountGrid"
Content="{Binding Source={StaticResource ResourceKey=WindowController}, Path=SelectedAccount}">
</ContentPresenter>
</Grid>

Resources