How to use WrapPanel's DataTemplate - wpf

I've a WrapPanel to show some elements. But I want to use DataTemplate to show them.
Here is my XAML code of WrapPanel
<WrapPanel Margin="10,57,12,10" x:Name="wrp1">
<WrapPanel.Resources>
<DataTemplate DataType="{x:Type local:DateItem}">
<Grid VerticalAlignment="Top" HorizontalAlignment="Stretch" Width="250" Height="300" Background="Blue">
<Label Content="{Binding Path=DateString}" FontSize="20" Cursor="Hand" Foreground="White" Background="Red" FontWeight="Bold" VerticalAlignment="Bottom" HorizontalAlignment="Left" Height="38" VerticalContentAlignment="Center" Padding="5,0,5,0"/>
</Grid>
</DataTemplate>
</WrapPanel.Resources>
</WrapPanel>
And this is the code of DateItem
public class DateItem : UIElement
{
public string DateString { get; set; }
}
When the window initialized, i'm creating one DateItem with DateString parameter and adding that to WrapPanel as child.
DateItem di = new DateItem();
di.DateString = "28.04.2014";
wrp1.Children.Add(di);
I think everything is fine but wrap panel shows nothing :(
Can you help me with this?

You have confused UI controls with DataTemplates which is used to define the presentation of your data. To render data, you have to set content of control which can be done using ContentControl.
Also, you can use ItemsControl if you want to add multiple times.
XAML:
<WrapPanel x:Name="wrp1">
<WrapPanel.Resources>
<DataTemplate DataType="{x:Type local:DateItem}">
<Grid VerticalAlignment="Top" HorizontalAlignment="Stretch" Width="250"
Height="300" Background="Blue">
<Label Content="{Binding Path=DateString}" FontSize="20" Cursor="Hand"
Foreground="White" Background="Red" FontWeight="Bold"
VerticalAlignment="Bottom" HorizontalAlignment="Left"
Height="38" VerticalContentAlignment="Center"
Padding="5,0,5,0"/>
</Grid>
</DataTemplate>
</WrapPanel.Resources>
<ItemsControl x:Name="itemsControl"/>
</WrapPanel>
Code behind:
DateItem di = new DateItem();
di.DateString = "28.04.2014";
itemsControl.Items.Add(di);
DateItem:
public class DateItem
{
public string DateString { get; set; }
}
In case you still interested in rendering it as a Control, you have to define default Style and not default template.
XAML:
<WrapPanel x:Name="wrp1">
<WrapPanel.Resources>
<Style TargetType="{x:Type local:DateItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid VerticalAlignment="Top" HorizontalAlignment="Stretch"
Width="250" Height="300" Background="Blue">
<Label
Content="{Binding Path=DateString, RelativeSource=
{RelativeSource Mode=TemplatedParent}}"
FontSize="20" Cursor="Hand" Foreground="White"
Background="Red" FontWeight="Bold"
VerticalAlignment="Bottom"
HorizontalAlignment="Left"
Height="38" VerticalContentAlignment="Center"
Padding="5,0,5,0"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</WrapPanel.Resources>
</WrapPanel>
Code behind:
DateItem di = new DateItem();
di.DateString = "28.04.2014";
wrp1.Children.Add(di);
DateItem:
public class DateItem : Control
{
public string DateString { get; set; }
}

Related

Button event is not triggered from Listbox item template wpf

Here is my xaml
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Blue"
BorderThickness="1"
HorizontalAlignment="Stretch">
<StackPanel HorizontalAlignment="Stretch"
Orientation="Horizontal">
<TextBlock Margin="5"
Text="{Binding Text}" />
<Button Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}"
Click="Remove">
<Button.Content>
<Image Source="{Binding DeleteIcon}"
Stretch="Fill"
Height="15"
Width="20" />
</Button.Content>
</Button>
</StackPanel>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
button event is not triggered in code behind or in viewmodel with command binding. How to fix this?
Trying this... It's work for me....
<ListBox Name="lstNumbers">
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Blue"
BorderThickness="1"
HorizontalAlignment="Stretch">
<StackPanel HorizontalAlignment="Stretch"
Orientation="Horizontal">
<TextBlock Margin="5"
Text="{Binding Text}" />
<Button Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}"
Click="Remove">
<Button.Content>
<Image Source="{Binding DeleteIcon}"
Stretch="Fill"
Height="15"
Width="20" />
</Button.Content>
</Button>
</StackPanel>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Cs Code:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
List<Numbers> list = new List<Numbers>();
list.Add(new Numbers() { Text ="1"});
list.Add(new Numbers() { Text = "2" });
lstNumbers.ItemsSource = list;
}
private void Remove(object sender, RoutedEventArgs e)
{
}
public class Numbers
{
public string Text { get; set; }
}

UserControl default value for dependency property of type DataTemplate

I have a simple EntriesViewModel that stores a list of items as well as supporting Add/Remove commands. (Add/Remove commanding left out)
public class EntriesViewModel
{
public ObservableCollection<string> Entries { get; private set; }
public EntriesViewModel()
{
Entries = new ObservableCollection<string>() { "One", "Two", "Three" };
}
}
To view this I have created a simple EntriesEditor usercontrol that uses a listbox to display the entries and buttons to Add/Remove (Add/Remove commanding left out)
public partial class EntriesEditor : UserControl
{
public EntriesEditor()
{
InitializeComponent();
}
}
<UserControl x:Class="UserControlDefaults.EntriesEditor"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:l="clr-namespace:UserControlDefaults"
VerticalAlignment="Top">
<DockPanel Height="200">
<UniformGrid Columns="2"
DockPanel.Dock="Bottom">
<Button Content="Add" />
<Button Content="Remove" />
</UniformGrid>
<ListBox ItemsSource="{Binding Entries}"
ItemTemplate="{Binding EntryTemplate, RelativeSource={RelativeSource AncestorType={x:Type l:EntriesEditor}}}"/>
</DockPanel>
And is used as so :
<l:EntriesEditor DataContext="{Binding EntriesViewModel}"/>
I now want the EntriesEditor to support the ability to define a custom ItemTemplate. So I add an EntryTemplate property.
public partial class EntriesEditor : UserControl
{
public DataTemplate EntryTemplate
{
get { return (DataTemplate)GetValue(EntryTemplateProperty); }
set { SetValue(EntryTemplateProperty, value); }
}
public static readonly DependencyProperty EntryTemplateProperty =
DependencyProperty.Register("EntryTemplate", typeof(DataTemplate), typeof(EntriesEditor), new PropertyMetadata(null));
public EntriesEditor()
{
InitializeComponent();
}
}
<UserControl x:Class="UserControlDefaults.EntriesEditor"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:l="clr-namespace:UserControlDefaults"
VerticalAlignment="Top">
<DockPanel Height="200">
<UniformGrid Columns="2"
DockPanel.Dock="Bottom">
<Button Content="Add" />
<Button Content="Remove" />
</UniformGrid>
<ListBox ItemsSource="{Binding Entries}"
ItemTemplate="{Binding EntryTemplate, RelativeSource={RelativeSource AncestorType={x:Type l:EntriesEditor}}}"/>
</DockPanel>
Which is used as so:
<l:EntriesEditor DataContext="{Binding EntriesViewModel}">
<l:EntriesEditor.EntryTemplate>
<DataTemplate>
<Border BorderThickness="1"
BorderBrush="Green"
Padding="5">
<ContentPresenter Content="{Binding}"/>
</Border>
</DataTemplate>
</l:EntriesEditor.EntryTemplate>
</l:EntriesEditor>
But now I want to define a default EntryTemplate within the EntriesEditor control, how would I do this?
The only way I can think of, is like this :
<UserControl x:Class="UserControlDefaults.EntriesEditor"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:l="clr-namespace:UserControlDefaults"
VerticalAlignment="Top">
<UserControl.Style>
<Style TargetType="{x:Type l:EntriesEditor}">
<Setter Property="EntryTemplate">
<Setter.Value>
<DataTemplate>
<Border BorderThickness="2"
BorderBrush="Red">
<ContentPresenter Content="{Binding}" />
</Border>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Style>
<DockPanel Height="200">
<UniformGrid Columns="2"
DockPanel.Dock="Bottom">
<Button Content="Add" />
<Button Content="Remove" />
</UniformGrid>
<ListBox ItemsSource="{Binding Entries}"
ItemTemplate="{Binding EntryTemplate, RelativeSource={RelativeSource AncestorType={x:Type l:EntriesEditor}}}"/>
</DockPanel>
But that doesn't seem right.

Closing Caliburn Micro View from a UserControl Button?

I have created a UserControl name TitleBar, which is placed in every view.
The TitleBar.xaml contains a Button to close the Window in which it contain.
How can i close a Caliburn Window using that Button.
TitleBar UserControl
<UserControl x:Class="JIMS.Controls.TitleBar"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006">
<Grid Style="{StaticResource TitleBar}">
<Rectangle HorizontalAlignment="Stretch" Height="7" Margin="0,0,-5,0" VerticalAlignment="Top" Fill="{DynamicResource DefaultBrush}"></Rectangle>
<Grid HorizontalAlignment="Left" Margin="-10,-5,0,0" Name="Logo">
<TextBlock Name="txtTitle" Style="{StaticResource Title}">JIMS</TextBlock>
<Ellipse HorizontalAlignment="Right" Margin="0,0,5,0" Width="20" Height="20">
<Ellipse.Fill>
<VisualBrush Stretch="Fill" Visual="{StaticResource appbar_settings_white}" />
</Ellipse.Fill>
</Ellipse>
</Grid>
<Grid HorizontalAlignment="Right">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,5,-4,0">
<Button Name="btnClose" Style="{StaticResource ChromeButtonStyle}" Click="btnClose_Click" IsTabStop="False">
<TextBlock TextWrapping="Wrap" Text="r" FontFamily="Webdings" Foreground="#FF919191" FontSize="13.333" />
</Button>
</StackPanel>
</Grid>
</Grid>
</UserControl>
TitleBar Usage in a View
<UserControl xmlns:my="clr-namespace:JIMS.Controls;assembly=JIMS.Controls" x:Class="JIMS.Views.Stock.UnitView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Name="Unit">
<Border Style="{StaticResource WindowBorderStyle}">
<StackPanel Orientation="Vertical">
<my:TitleBar Title="unit creation"/>
<StackPanel Visibility="{Binding ControlVisiblity}" Orientation="Horizontal" Margin="0,5,0,5">
<StackPanel Orientation="Vertical" Margin="10,0,0,0">
<Label>Short Name :</Label>
<Label>Unit Name :</Label>
</StackPanel>
<StackPanel Orientation="Vertical" Width="200" Margin="0,0,10,0">
<TextBox Name="txtShortName" Text="{Binding Path=UnitShort}"></TextBox>
<TextBox Name="txtUnitName" Text="{Binding Path=UnitName}"></TextBox>
</StackPanel>
</StackPanel>
<Expander Style="{StaticResource DisplayExpander}" IsExpanded="{Binding IsDisplayExpanded}" Header="display units">
<StackPanel Orientation="Horizontal" Margin="0,5,0,5" Visibility="{Binding DisplayVisiblity}">
<DataGrid AutoGenerateColumns="True" Height="200" MinWidth="300" ItemsSource="{Binding Display}"></DataGrid>
</StackPanel>
</Expander>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Button Name="SaveUnit" Style="{StaticResource MetroButton}">Save</Button>
</StackPanel>
</StackPanel>
</Border>
</UserControl>
In your TitleBar control define a RoutedEvent like this
public event RoutedEventHandler CloseClick
{
add { AddHandler(CloseClickEvent, value); }
remove { RemoveHandler(CloseClickEvent, value); }
}
public static readonly RoutedEvent CloseClickEvent = EventManager.RegisterRoutedEvent(
"CloseClick", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TitleBar));
void RaiseCloseClickEvent()
{
var newEventArgs = new RoutedEventArgs(TitleBar.CloseClickEvent);
RaiseEvent(newEventArgs);
}
private void btnClose_Click(object sender, RoutedEventArgs e)
{
RaiseCloseClickEvent();
}
And attach the btnClose_Click event handler to the btnClose control in your TitleBar
Now, when you use your TitleBar add an action like this
<my:TitleBar Title="This is the title">
<i:Interaction.Triggers>
<i:EventTrigger EventName="CloseClick">
<cal:ActionMessage MethodName="Close"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</my:TitleBar>
This will call the method Close on your viewmodel when the the CloseClickEvent is raised on the TitleBar.
For closing the window, you could derive your viewmodel from Screen and add the following snippet
public void Close()
{
TryClose();
}

ListView like WindowsLiveMessenger

<ListView Margin="0" Background="White" ItemContainerStyle="{DynamicResource ListViewItemStyle}" ItemTemplate="{DynamicResource DataTemplate}">
<ListView.Resources>
<Style x:Key="ListViewItemStyle" TargetType="{x:Type ListViewItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<Grid/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<DataTemplate x:Key="DataTemplate">
<Grid Width="Auto">
<Label Content="" HorizontalAlignment="Center" Margin="62,8,8,8" Width="100" VerticalAlignment="Center" Height="30"/>
<Image HorizontalAlignment="Left" Margin="8,8,0,8" Width="50" VerticalAlignment="Stretch" Height="30"/>
</Grid>
</DataTemplate>
</ListView.Resources>
<ListViewItem>
</ListViewItem>
</ListView>
i'm new to blend !!
how to add items from code that contain those 2 controls
this question is similar to
How to write ListViewItem that contain image , text and button?
You are using a DataTemplate that should be applied to the items, but you do not bind the relevant properties at all.
i.e.
<DataTemplate x:Key="DataTemplate">
<Grid Width="Auto">
<Label Content="{Binding Name}"
HorizontalAlignment="Center" Margin="62,8,8,8" Width="100" VerticalAlignment="Center" Height="30"/>
<Image Source="{Binding ImageUrl}"
HorizontalAlignment="Left" Margin="8,8,0,8" Width="50" VerticalAlignment="Stretch" Height="30"/>
</Grid>
</DataTemplate>
See those two bindings? Your data-objects need to provide those public properties, i named them Name and ImageUrl here.
// Data-object class example
public class Contact
{
public string Name { get; set; }
public string ImageUrl { get; set; }
//...
}
If your data-object supports that you can just add items of that type to the ListView and it should display as you want it to.
This might not make much sense to you, if so, make sure to read introductory material first:
Data Binding Overview
Data Templating Overview

Removing left and right border sides from listbox datatemplate

Currently I have specified borders for all datatemplated items in my horizontal listbox which is fine because I DO want borders for all individual listboxitems, but I would like to remove the left border from the first item and the right border from the last item. Is this even possible?
Xaml:
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical" Background="DimGray">
<Border BorderBrush="White" BorderThickness="1">
<Canvas Height="80" Width="140">
<TextBlock Text="{Binding Name}" TextAlignment="Center" Canvas.Top="22" Height="80" Width="140" FontSize="26"></TextBlock>
</Canvas>
</Border>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
Thanks
It is, with a DataTemplateSelector, you just need to implement the logic to select the correct DataTemplate, here's a fulle example with your code. You should be able to just copy / paste the following code in your project. There are comments in there that explain what's going on. Hope it helps!
XAML:
<Window x:Class="StackOverflowTests.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:local="clr-namespace:StackOverflowTests"
Title="Window1"
x:Name="window1"
Width="800"
Height="600">
<Window.Resources>
<!-- Instantiate the DataTemplateSelector -->
<local:ItemDataTemplateSelector x:Key="ItemDataTemplateSelector" />
</Window.Resources>
<!-- Assign the DataTemplateSelector to the ListBox's ItemTemplateSelector -->
<ListBox Margin="8" ItemsSource="{Binding}" ItemTemplateSelector="{StaticResource ItemDataTemplateSelector}">
<ListBox.Resources>
<!-- Template without Left border -->
<DataTemplate x:Key="firstItemTemplate">
<StackPanel Orientation="Vertical" Background="DimGray">
<Border BorderBrush="Red" BorderThickness="0,1,1,1">
<Canvas Height="80" Width="140">
<TextBlock Text="{Binding Name}" TextAlignment="Center" Canvas.Top="22" Height="80" Width="140" FontSize="26"></TextBlock>
</Canvas>
</Border>
</StackPanel>
</DataTemplate>
<!-- Template with all borders -->
<DataTemplate x:Key="regularItemTemplate">
<StackPanel Orientation="Vertical" Background="DimGray">
<Border BorderBrush="Red" BorderThickness="1,1,1,1">
<Canvas Height="80" Width="140">
<TextBlock Text="{Binding Name}" TextAlignment="Center" Canvas.Top="22" Height="80" Width="140" FontSize="26"></TextBlock>
</Canvas>
</Border>
</StackPanel>
</DataTemplate>
<!-- Template without the Right border -->
<DataTemplate x:Key="lastItemTemplate">
<StackPanel Orientation="Vertical" Background="DimGray">
<Border BorderBrush="Red" BorderThickness="1,1,0,1">
<Canvas Height="80" Width="140">
<TextBlock Text="{Binding Name}" TextAlignment="Center" Canvas.Top="22" Height="80" Width="140" FontSize="26"></TextBlock>
</Canvas>
</Border>
</StackPanel>
</DataTemplate>
</ListBox.Resources>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
</Window>
C#:
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
namespace StackOverflowTests
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
this.DataContext = new List<Person>()
{
new Person() { Name = "Jim Morrison" },
new Person() { Name = "Ozzy Osbourne" },
new Person() { Name = "Slash" },
new Person() { Name = "Jimmy Page" }
};
}
}
public class Person
{
public string Name { get; set; }
}
public class ItemDataTemplateSelector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
FrameworkElement element = container as FrameworkElement;
// get the ListBoxItem
ListBoxItem listBoxItem = element.TemplatedParent as ListBoxItem;
// get the ListBoxItem's owner ListBox
ListBox listBox = ItemsControl.ItemsControlFromItemContainer(listBoxItem) as ListBox;
// get the index of the item in the ListBox
int index = listBox.Items.IndexOf(item);
// based on the index select the template
if (index == 0)
return element.FindResource("firstItemTemplate") as DataTemplate;
else if (index == listBox.Items.Count - 1)
return element.FindResource("lastItemTemplate") as DataTemplate;
else
return element.FindResource("regularItemTemplate") as DataTemplate;
}
}
}

Resources