Switch datatemplate depending on a selected string value in combobox - wpf

Based on a selected string value in the combobox I want to either show red/blue datatempalte inside the grid.
Can this be done without a ContentControl?
<UserControl.Resources >
<DataTemplate x:Key="red">
<TextBox Text="red" />
</DataTemplate>
<DataTemplate x:Key="blue">
<TextBox Text="blue" />
</DataTemplate>
</UserControl.Resources>
<ComboBox ??? />
<Grid>
// Show red or blue datatemplate here
</Grid>

Why not use a ContentControl?
To make this work simply i would put the templates in an array, which the ComboBox then can bind to:
<x:Array x:Key="templates" Type="{x:Type DataTemplate}">
<DataTemplate>
<DataTemplate.Resources>
<sys:String x:Key="DisplayString">Red</sys:String>
</DataTemplate.Resources>
<TextBox Text="red" />
</DataTemplate>
<DataTemplate>
<DataTemplate.Resources>
<sys:String x:Key="DisplayString">Blue</sys:String>
</DataTemplate.Resources>
<TextBox Text="blue" />
</DataTemplate>
</x:Array>
<ComboBox Name="combo" ItemsSource="{StaticResource templates}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Resources[DisplayString]}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<Grid>
<ContentControl ContentTemplate="{Binding SelectedItem, ElementName=combo}" />
</Grid>

Related

WPF DataTemplate and binding with TextBlock

<Window.Resources>
<DataTemplate x:Key="pointGroupTemplate" DataType="{x:Type ac:PointGroup}">
<TextBlock Text="{Binding Name}" />
</DataTemplate>
<DataTemplate x:Key="tt2" DataType="{x:Type ac:PointGroup}">
<TextBlock Text="{Binding PointsCount}"/>
</DataTemplate>
</Window.Resources>
the first template works well with:
<ComboBox x:Name="comboBox1" ItemTemplate="{StaticResource pointGroupTemplate}" SelectionChanged="ComboBox1_SelectionChanged"
Height="25" Margin="0,5,0,5">
but i want to use the second one in a textblock
<TextBlock x:Name="textBlock1" Text="{Binding ElementName=comboBox1 ,Path=SelectedItem ?????}"/>
anyhelp.
In order to have a DataTemplate applied, you need a ContentPresenter or ContentControl:
<ContentControl ContentTemplate="{StaticResource tt2}"
Content="{Binding SelectedItem, ElementName=comboBox1}"/>

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>

WPF binding Listbox layoutpanel

I´m using devexpress and I want to do a binding with a Listbox, but I have an error. Here my code:
<ListBox x:Name="_list" >
<ListBox.ItemTemplate>
<DataTemplate>
<dxd:LayoutPanel
Caption="{Binding nameList}"
AllowHide ="False" AllowFloat="False"
GotFocus="panel_GotFocus" >
<TextBox Text="Hello" />
</dxd:LayoutPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
With this code, Caption {Binding nameList} is empty.
I have tried this.
<ListBox x:Name="_list" >
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<TextBox Text="{Binding nameList}" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
In this case, text in TextBox is correct, I need to use the first code.
You seem to be a bit confused about how to use this ListBox. First, you need a collection property to bind to the ListBox.ItemsSource property. Let's say you have a collection of User objects called Users:
<ListBox ItemSource="{Binding Users}" />
Now we want to define how each User should be displayed... all the properties of the User class will be available to the Binding inside the DataTemplate. Let's say that the User class has two properties; Name and Age:
<DataTemplate DataType="{x:Type YourDataTypeNamespace:User}">
<StackPanel>
<TextBox Text="{Binding Name}" />
<TextBox Text="{Binding Age}" />
</StackPanel>
</DataTemplate>
Then putting it all together:
<ListBox ItemSource="{Binding Users}">
<ListBox.ItemTemplate>
<DataTemplate DataType="{x:Type YourDataTypeNamespace:User}">
<StackPanel>
<TextBox Text="{Binding Name}" />
<TextBox Text="{Binding Age}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

Add an event on ListBoxItems build with ItemTemplate

I have a ListBox like this :
<ListBox DataContext="{Binding UpdateSourceTrigger=PropertyChanged}"
ItemsSource="{Binding UpdateSourceTrigger=PropertyChanged}"
ListBoxItem.Selected="ListBoxItem_Selected">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<DockPanel>
<Label Content="{Binding Path=Attribute[rdv].Value, UpdateSourceTrigger=PropertyChanged}" />
</DockPanel>
<DockPanel>
<Label Content="{Binding Path=Attribute[type].Value, UpdateSourceTrigger=PropertyChanged}" />
<Label Content="{Binding Path=Element[ville].Attribute[saisie].Value, UpdateSourceTrigger=PropertyChanged}" />
<Label Content=":" />
<Label Content="{Binding Path=Element[adresse].Attribute[saisie].Value, UpdateSourceTrigger=PropertyChanged}" />
</DockPanel>
<Separator />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I whant to rise an event when an ListeBoxItem is selected.
As you can see, I've tried with ListBoxItem.Selected="ListBoxItem_Selected" but it does not work.
Do you have an idea ?
Tanks by advance !
You handler doesn't get called because the Selected event is already handled by the ListBox. You should handle the SelectionChanged event in the ListBox instead:
<ListBox DataContext="{Binding UpdateSourceTrigger=PropertyChanged}"
ItemsSource="{Binding UpdateSourceTrigger=PropertyChanged}"
SelectionChanged="ListBox_SelectionChanged">
Alternatively, you can use an ItemContainerStyle to attach the handler to every ListBoxItem:
<ListBox DataContext="{Binding UpdateSourceTrigger=PropertyChanged}"
ItemsSource="{Binding UpdateSourceTrigger=PropertyChanged}">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<EventSetter Event="Selected" Handler="ListBoxItem_Selected"/>
</Style>
</ListBox.ItemContainerStyle>

WPF : InputBindings on a StackPanel

I want to put a command on a ListBoxItem. The ListBoxItem use a DataTemplate composed of a StackPanel (containing an Image and a TextBlock, both using Binding). I want that the doubleclick on that ListBoxItem fire the command.
I have tried this :
<DataTemplate>
<StackPanel>
<StackPanel.Resources>
<CommonUI:CommandReference x:Key="DoubleClickCommand" Command="{Binding Path=DefaultCommand}" />
</StackPanel.Resources>
<StackPanel.InputBindings>
<MouseBinding Gesture="LeftDoubleClick" Command="{StaticResource DoubleClickCommand}" />
</StackPanel.InputBindings>
<Image Source="{Binding Path=Thumbnail, IsAsync=True}" IsHitTestVisible="False"/>
<TextBlock Text="{Binding Path=Name}" IsHitTestVisible="False">
</StackPanel>
</DataTemplate>
I have also tried to put the Command Resources on a StackPanel containing this StackPanel, without any change.
I am certain of my binding because when I put the InputBindings part on the TextBlock, it works.
Thanks
Try handling the event in the ListBox instead of the StackPanel:
<ListBox>
<ListBox.Resources>
<CommonUI:CommandReference x:Key="DoubleClickCommand" Command="{Binding Path=DefaultCommand}" />
</ListBox.Resources>
<ListBox.InputBindings>
<MouseBinding Gesture="LeftDoubleClick" Command="{StaticResource DoubleClickCommand}" />
</ListBox.InputBindings>
<DataTemplate>
<StackPanel>
<Image Source="{Binding Path=Thumbnail, IsAsync=True}" />
<TextBlock Text="{Binding Path=Name}" />
</StackPanel>
</DataTemplate>
</ListBox>
My code finally looks like this :
<DataTemplate>
<StackPanel Orientation="Vertical">
<StackPanel.Resources>
<CommonUI:CommandReference x:Key="DoubleClickCommand" Command="{Binding Path=DefaultCommand}" />
</StackPanel.Resources>
<StackPanel.InputBindings>
<MouseBinding Gesture="LeftDoubleClick" Command="{StaticResource DoubleClickCommand}" />
</StackPanel.InputBindings>
<Image Source="{Binding Path=Thumbnail, IsAsync=True}" />
<TextBlock Text="{Binding Path=Name}" />
</StackPanel>
</DataTemplate>
Thanks anyway, Mr Poulin.

Resources