Can I access DataTemplate into codebehind - wpf

I am using WPF and I have DataTemplate that is i want to access into the codebehind
how I can use this?
Thanks.

<Window.Resources>
<DataTemplate x:Key="PersonDataTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=Name}" />
<TextBlock Text="{Binding Path=Age}" />
</StackPanel>
</DataTemplate>
</Window.Resources>
public Window1()
{
InitializeComponent();
DataTemplate dataTemplate = FindResource("PersonDataTemplate") as DataTemplate;
}

Related

Binding to ViewModel instance from View

I have program which initializes PersonsViewModel in MainWindowViewModel's constructor.
public MainWindowViewModel()
{
PersonsViewModel viewModel = new PersonsViewModel();
}
In MainWindow.xaml, PersonsViewModel and PersonsView are connected.
<Window.Resources>
<DataTemplate DataType="{x:Type vm:PersonsViewModel}">
<vw:PersonsView />
</DataTemplate>
</Window.Resources>
I use viewModel as ItemsControl ItemsSource.
<ItemsControl ItemsSource="{Binding viewModel}" Margin="4" />
Now my program opens UserControl and I need to set instance of PersonsViewModel to UserControl.DataContext.
<UserControl.DataContext>
<vm:PersonsViewModel />
</UserControl.DataContext>
Am I creating a new instance of PersonsViewModel. If I am doing so, then how I can bind it to PersonsViewModel instance? Because I have following code in UserControl. I have PersonsList bound to ItemsSource and I need to bind Command to PersonsViewModel instance.
<ItemsControl ItemsSource="{Binding PersonsList}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBox Width="50" Text="{Binding Name}" />
<Button Content="Ok" Width="20" Margin="3" Command="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type UserControl}}, Path=DataContext.Command}" CommandParameter="{Binding Name}" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
You can remove the UserControl.DataContext and Add ItemsControl.ItemTemplate. Since each ItemsControl is bound to List of person viewmodel. Each item will get the viewmodel as its datacontext. Refer the below code.
<ItemsControl ItemsSource="{Binding ViewModels}" Margin="4">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type vm:PersonsViewModel}">
<vw:PersonsView />
</DataTemplate>
</ItemsControl.ItemTemplate>

WPF binding from ListBox ItemTemplate

I have a problem binding from ListBox Itemtemplate that contains an Expander with its own HeaderTemplate and ContentTemplate.
<ListBox ItemsSource="{Binding Feeds}">
<ListBox.ItemTemplate>
<DataTemplate>
<Expander Content="{Binding Text}"
Header="{Binding Title}">
<Expander.HeaderTemplate>
<DataTemplate>
<DockPanel >
<TextBlock Text="{Binding PublishDate}" />
<TextBlock Text="{Binding}" />
</DockPanel>
</DataTemplate>
</Expander.HeaderTemplate>
<Expander.ContentTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<Image Source="{Binding ImageURL}" />
<TextBlock Text="{Binding}" />
</StackPanel>
</DataTemplate>
</Expander.ContentTemplate>
</Expander>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
The PublishDate and ImageURL bindings don't work and I'd like to bind them to properties in the object Feed:
Public Class Feed
Public Property Title As String
Public Property PublishDate As DateTime
Public Property Text As String
Public Property ImageURL As String
End Class
I tried FindAncestor in the binding to find the ListBoxItem but it didn't help me.
the Content of the Expander serves as the DataContext for the ContentTemplate and the Header for the HeaderTemplate.
Set Content="{Binding}" and Header="{Binding}" instead. This sets the DataContext of both templates to the DataContext of the ListBoxItem (i.e. a Feed).

How can I specify multiple DataTemplate in windows.resources for use by a ContentControl

How can I specify multiple DataTemplate in windows.resources for use by a ContentControl?
My code:
<Window.Resources>
<DataTemplate x:Key="CustomerTemplate" DataType="{x:Type local:Customer}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding FirstName}"/>
<TextBlock Text=" ("/>
<TextBlock Text="{Binding Occupation}"/>
<TextBlock Text=")"/>
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="PersonTemplate" DataType="{x:Type local:Person}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding FirstName}"/>
<TextBlock Text=" - "/>
<TextBlock Text="{Binding LastName}"/>
</StackPanel>
</DataTemplate>
</Window.Resources>
Thank you so much!
Use DataTemplateSelector to return the Datatemplate you want to be applied..
<ContentControl ContentTemplateSelector="{StaticResource MyTemplateSelector}"/>
here MYtemplateselector is DataTemplateSelector, in Select() method of selector you can check for the property bound to contentcontrol and return the corresponding Datatemplate.
Thanks
Remove x:Key from DataTemplate and try this:
<ContentControl Name="CustomerContentControl">
<local:Customer />
</ContentControl>
<ContentControl Name="PersonContentControl">
<local:Person />
</ContentControl>
In this article, Josh Smith show, how to get access the elements that are in the DataTemplate:
How to use FindName with a ContentControl

Question on Hierarchial data template in WPF Tree

I have a WPF tree which needs to show some nodes. Lets say I have 2 types of entities, EntityA and EntityB. Both these entities implement a common interface IEntity. Now, EntityA will have a collection of EntityB elements as well as EntityA elements. How can I show this via a HierarchicalDataTemplate ?
I am exposing a ObservableCollection() called "DisplayItems" in my VM that will contain elements of EntityA type.
Both EnittyA and EntityB will have another ObservableCollection called "ItemCollection". For EntityA, the ItemCollection list should ideally contain entities of EntityA and EntityB types.
The current HierarchicalDataTemplate and the XAML that I am using is as follows:
<HierarchicalDataTemplate ItemsSource="{Binding Path=ItemCollection}" DataType="{x:Type Entities:EntityB}">
<Grid>
<StackPanel Orientation="Horizontal" x:Name="compositeCT">
<Image Source="/Images/EntityB.png" Width="15" Height="15"/>
<Label Foreground="Blue" Content="{Binding Path=Name}"/>
<Label Foreground="Black" Content=" = "/>
<Label Foreground="Blue" Content="{Binding Path=CompositeLabel}"/>
</StackPanel>
<StackPanel Orientation="Horizontal" x:Name="nCompositeCT">
<Image Source="/Images/EntityB.png" Width="15" Height="15"/>
<TextBlock Foreground="Blue" Text="{Binding Path=Name}"/>
</StackPanel>
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate>
<TextBlock Foreground="Green" Text="{Binding}"/>
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Path=ItemCollection}" DataType="{x:Type Entities:EntityA}">
<StackPanel Orientation="Horizontal" >
<Image Source="/Images/ElementA.png" Margin="3" Width="15" Height="15" Focusable="False"/>
<TextBlock Foreground="Red" Text="{Binding Path = Name}" Focusable="False"/>
</StackPanel>
</HierarchicalDataTemplate>
<TreeView x:Name="tvMyTree"
ItemsSource="{Binding DisplayItems}"
AllowDrop="True"
VirtualizingStackPanel.IsVirtualizing="True"
VirtualizingStackPanel.VirtualizationMode="Recycling"
ScrollViewer.IsDeferredScrollingEnabled="True"
Margin="5"
TreeViewItem.Expanded="OnTreeViewItemExpanded"
TreeViewItem.Selected="OnTreeViewItemSelected"
/>
You can define two HierarchicalDataTemplates you are fine. And in the place of TextBlock you can put whatever complex visualization you need depending on the other Properties of your EntityA and EntityB
<HierarchicalDataTemplate DataType="{x:Type local:EnittyA}" ItemsSource="{Binding ItemCollection}" >
<TextBlock Text="{Binding Name}"/>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type local:EnittyB}" ItemsSource="{Binding ItemCollection}" >
<TextBlock Text="{Binding Name}"/>
</HierarchicalDataTemplate>
I suppose ItemTemplateSelector fits perfect to your requirements. ItemTemplateSelector is inherited, so you should not care about endpoint receiver of template. Receiver (item container) just addresses to selector and the last one returns proper template according to DataType:
public class LayoutItemTemplateSelectorItem
{
public Type TargetType
{
get;
set;
}
public DataTemplate Template
{
get;
set;
}
}
[ContentProperty("Items")]
public class LayoutItemTemplateSelector : DataTemplateSelector
{
public LayoutItemTemplateSelector()
{
this.Items = new Collection<LayoutItemTemplateSelectorItem>();
}
public Collection<LayoutItemTemplateSelectorItem> Items
{
get;
private set;
}
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
var component = (LayoutItem)item;
var typeToSearch = component.GetType();
var foundItem = this.Items
.Where(i => i.TargetType == typeToSearch)
.FirstOrDefault();
if (foundItem != null)
{
return foundItem.Template;
}
throw new Exception(string.Format(Properties.Resources.AppropriateTemplateNotFound, typeToSearch.FullName));
}
}
Usage in XAML:
<UserControl ...>
<UserControl.Resources>
<ResourceDictionary>
<HierarchicalDataTemplate x:Key="EntityBTemplate"
ItemsSource="{Binding Path=ItemCollection}"
DataType="{x:Type Entities:EntityB}">
...
</HierarchicalDataTemplate>
<HierarchicalDataTemplate x:Key="EntityATemplate"
ItemsSource="{Binding Path=ItemCollection}"
DataType="{x:Type Entities:EntityA}">
...
</HierarchicalDataTemplate>
<LayoutItemTemplateSelector x:Key="TemplateSelector">
<LayoutItemTemplateSelectorItem TargetType="{x:Type EntityA}"
Template="{StaticResource EntityATemplate}"/>
<LayoutItemTemplateSelectorItem TargetType="{x:Type EntityB}"
Template="{StaticResource EntityBTemplate}"/>
</LayoutItemTemplateSelector>
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<TreeView ItemsSource="{Binding DisplayItems}"
ItemTemplateSelector="{StaticResource TemplateSelector}"/>
</Grid>
</UserControl>

Silverlight Data Binding for Collection in Stack Panel

I'm new to Silverlight, so I don't have a complete grasp of all the controls at my disposal. What I would like to do is use databinding and a view model to maintain a collection of items. Here is some mock code for what I'd like to do:
Model
public class MyItem
{
public string DisplayText { get; set; }
public bool Enabled { get; set; }
}
ViewModel
public class MyViewModel : INotifyPropertyChanged
{
private ObservableCollection<MyItem> _myItems = new ObservableCollection<MyItem>();
public ObservableCollection<MyItem> MyItems
{
get { return _myItems; }
set
{
_myItems = value
NotifyPropertyChanged(this, "MyItems");
}
}
}
View
<Grid x:Name="LayoutRoot" Background="White">
<StackPanel ItemsSource="{Binding MyItems}">
<StackPanel Orientation="Horizontal">
<CheckBox "{Binding Enabled, Mode=TwoWay}"></CheckBox>
<TextBlock Text="{Binding DisplayText, Mode=TwoWay}" />
</StackPanel>
</StackPanel>
</Grid>
So my end goal would be that every time I add another MyItem to the MyItems collection it would create a new StackPanel with checkbox and textblock. I don't have to use a stack panel but just thought I'd use that for this sample.
Looks like you want a <ListBox>, then set the <ListBox.ItemTemplate> to your <StackPanel> something like this.....
<ListBox ItemsSource=”{Binding Classes, Source={StaticResource model}}”>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox "{Binding Enabled, Mode=TwoWay}"/>
<TextBlock Text="{Binding DisplayText, Mode=TwoWay}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
here is a great example (it's WPF, but should only be minor changes for silverlight)
yes, looks like you want a <ListBox>
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SilverlightApplication4.MainPage"
Width="640" Height="480">
<UserControl.Resources>
<DataTemplate x:Key="ItemTemplate">
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked="{Binding Enabled, Mode=TwoWay}"/>
<TextBlock Text="{Binding DisplayText}"/>
</StackPanel>
</DataTemplate>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="White" DataContext="{Binding Source={StaticResource SampleDataSource}}">
<ListBox Margin="0,0,8,0" ItemTemplate="{StaticResource ItemTemplate}" ItemsSource="{Binding Collection}"/>
</Grid>
This code will give you a ListBox with all your Data bound to a Checkbox and TextBlock with the Checkbox first and TextBox next to it.

Resources