In a silverlight 5 mvvm project I have the following code:
View:
<navigation:Page x:Class="LobDemo.View.MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="600"
DataContext="{Binding Source={StaticResource Locator}, Path=Main}" >
<Grid x:Name="LayoutRoot">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<toolkit:DockPanel Grid.Column="0">
<toolkit:Accordion Name="accordion1"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
ItemsSource="{Binding Path=MenuItems}"
Margin="5,5,5,5">
<toolkit:Accordion.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Name}" />
</DataTemplate>
</toolkit:Accordion.ItemTemplate>
<toolkit:Accordion.ContentTemplate>
<DataTemplate>
<ListBox ItemsSource="{Binding Path=SubMenuItems}"
Margin="2 2 0 0"
BorderThickness="0"
SelectedItem="{Binding Path=SelectedMenuItem, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Name}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DataTemplate>
</toolkit:Accordion.ContentTemplate>
</toolkit:Accordion>
</toolkit:DockPanel>
</Grid>
ViewModel: (I'm only showing the required properties)
public ObservableCollection<MenuItem> MenuItems
{
get { return _menuItems; }
set
{
_menuItems = value;
RaisePropertyChanged("MenuItems");
}
}
public object SelectedMenuItem
{
get { return _selectedMenuItem; }
set
{
_selectedMenuItem = value;
RaisePropertyChanged("SelectedMenuItem");
}
}
MenuItem:
public string Name { get; set; }
public ObservableCollection<SubMenuItem> SubMenuItems { get; set; }
SubMenuItem:
public string Name { get; set; }
The code is working fine, my MenuItems are visible in the accordion control, the SubMenuItems are also loaded in the listbox. The problem comes when I select one of the items in the listbox, I want the selected item reported back to my ViewModel as SelectedMenuItem. But the property SelectedMenuItem is never filled, so I'm guessing the code cannot resolve the location of the property.
Can somebody point out what I'm doing wrong?
I found the solution for my problem, I've updated the Accordion.ContentTemplate code in the view, the code now looks like this:
<toolkit:Accordion.ContentTemplate>
<DataTemplate>
<ListBox ItemsSource="{Binding Path=SubMenuItems}"
Margin="2 2 0 0"
BorderThickness="0"
SelectedItem="{Binding RelativeSource={RelativeSource AncestorType=navigation:Page}, Path=DataContext.SelectedMenuItem, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Name}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DataTemplate>
With this code, the view now finds the SelectedMenuItem property in the ViewModel
Related
I am trying to set the alignment of the contents in the ListBox below. I have wrapped the ListBox inside a ScrollViewer to make it scroll horizontally.
Each element of the Listbox is a Stackpanel and I am trying to align each one to the Top and to set the width to auto for each.
Right now, the stackpanels are centered vertically and the width of each one is the same and is represented by the width of the largest panel.
I have put HorizontalContentAlignment="Left" and VerticalContentAlignment="Top", as I have read in similar posts but it does not change anything.
<ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto" >
<ListBox ItemsSource="{Binding Termene}" SelectedItem="{Binding SelectedTermenCondica}" HorizontalContentAlignment="Left" VerticalContentAlignment="Top">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Rows="1" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate >
<DataTemplate >
<StackPanel Margin="2" >
<StackPanel.Resources>
<CollectionViewSource Source="{Binding Dosare}" x:Key="dosareView" IsLiveSortingRequested="True" >
<CollectionViewSource.SortDescriptions>
<scm:SortDescription PropertyName="Ora" />
</CollectionViewSource.SortDescriptions>
</CollectionViewSource>
<Style x:Key="NoFocusColumStyle" TargetType="{x:Type DataGridCell}">
<Setter Property="IsHitTestVisible" Value="False"/>
</Style>
</StackPanel.Resources>
<TextBlock Text="{Binding NumeComplet, StringFormat='Complet {0}'}" HorizontalAlignment="Center" FontWeight="Bold" VerticalAlignment="Top"></TextBlock>
<TextBlock Text="{Binding TermenCB, StringFormat='Termen: {0}'}" HorizontalAlignment="Center" FontWeight="Bold" VerticalAlignment="Top"></TextBlock>
<DataGrid IsSynchronizedWithCurrentItem="True" CellStyle="{StaticResource NoFocusColumStyle}" IsReadOnly="True" ItemsSource="{Binding Source={StaticResource dosareView}}" Style="{StaticResource DGRapaorte}" AutoGenerateColumns="False" >
<DataGrid.Columns>
<DataGridTextColumn Header="Nr. dosar" Binding="{Binding NumarDosar}"/>
<DataGridTextColumn CanUserSort="True" SortDirection="Ascending" SortMemberPath="Ora" Header="Ora" Binding="{Binding Ora, StringFormat={}{0:HH:mm}}" />
<DataGridTextColumn Header="Obiect" Binding="{Binding Obiect}"/>
</DataGrid.Columns>
</DataGrid>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</ScrollViewer>
Later edit:
I have added some data (three items in Termene to show you how it looks. I have blurred them out, but you can see the issue.
Here is how it looks right now:
Scrolled further:
Now, here is how I would like it to look like:
As you can see, the height and width of every item is set with the width and height of the largest item.
Replace the Uniformgrid part with this:
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
Source: https://stackoverflow.com/a/3565590/4394435
This example worked for me:
<Window x:Class="WpfMVVM.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfMVVM"
mc:Ignorable="d"
Title="MainWindow" Height="500" Width="500">
<ListBox ItemsSource="{Binding Items}" VerticalContentAlignment="Top">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="2">
<TextBlock Text="test" HorizontalAlignment="Center" FontWeight="Bold" />
<TextBlock Text="blub" HorizontalAlignment="Center" FontWeight="Bold" />
<DataGrid IsSynchronizedWithCurrentItem="True" IsReadOnly="True"
ItemsSource="{Binding DataGridItems}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Nr. dosar" Binding="{Binding Text}" />
</DataGrid.Columns>
</DataGrid>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Window>
with this viewModel
public class DataViewModel
{
public DataViewModel()
{
}
public List<Item> Items { get; set; } = new List<Item>()
{
new Item(){DataGridItems = new List<DataGridItem>(){new DataGridItem() { Text = "a"} }},
new Item(){DataGridItems = new List<DataGridItem>(){new DataGridItem() { Text = "aaaaaaaaaaa"} }},
new Item(){DataGridItems = new List<DataGridItem>(){new DataGridItem() { Text = "aaaaaaaaaaaaaaaaaa"} }},
new Item(){DataGridItems = new List<DataGridItem>()
{
new DataGridItem() { Text = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"},
new DataGridItem() { Text = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"},
new DataGridItem() { Text = "aaa"},
new DataGridItem() { Text = "aaaaaaaaaa"}
}}
};
}
public class Item
{
public List<DataGridItem> DataGridItems { get; set; }
}
public class DataGridItem
{
public string Text { get; set; }
}
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>
I have a frustrating problem that I would much appreciate some help with. I have a ListView within a ViewBox and I can't get the items within the ListView to stretch horizontally.
Here is the XAML:
<Window x:Class="WpfApplication3.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication3"
Title="Window1">
<Window.Resources>
<local:Inning x:Key="inning">
<local:Inning.Skins>
<local:Skin SkinNumber="1"></local:Skin>
<local:Skin SkinNumber="2"></local:Skin>
<local:Skin SkinNumber="3"></local:Skin>
</local:Inning.Skins>
</local:Inning>
</Window.Resources>
<Grid DataContext="{StaticResource inning}">
<Grid.RowDefinitions>
<RowDefinition Height="auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<TextBlock Background="Black"
Text="SKINS"
Foreground="White"
FontSize="80"
FontWeight="Bold"
HorizontalAlignment="Center"></TextBlock>
<Grid Margin="2"
Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Viewbox>
<ListView Name="lvSkinNumbers"
ItemsSource="{Binding Skins}"
HorizontalAlignment="Stretch"
Background="Black"
VerticalAlignment="Stretch"
VerticalContentAlignment="Stretch">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock FontSize="250"
VerticalAlignment="Stretch"
LineStackingStrategy="BlockLineHeight"
Margin="2"
TextAlignment="Center"
HorizontalAlignment="Stretch"
Background="Black"
Foreground="White"
Text="{Binding SkinNumber}"></TextBlock>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Viewbox>
<Viewbox Grid.Column="1">
<ListView Name="lvFirstInningSkins"
ItemsSource="{Binding Skins}"
Grid.Column="1"
HorizontalContentAlignment="Stretch"
Background="Black">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock FontSize="250"
VerticalAlignment="Stretch"
LineStackingStrategy="BlockLineHeight"
Margin="2"
TextAlignment="Center"
HorizontalAlignment="Stretch"
Background="Green"
Foreground="White"
Text="{Binding SkinNumber}"></TextBlock>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Viewbox>
<Viewbox Grid.Column="2"
HorizontalAlignment="Stretch">
<ListView Name="lvSecondInningSkins"
ItemsSource="{Binding Skins}"
Grid.Column="2"
HorizontalAlignment="Stretch"
Background="Black">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock FontSize="250"
VerticalAlignment="Stretch"
LineStackingStrategy="BlockLineHeight"
Margin="2"
TextAlignment="Center"
HorizontalAlignment="Stretch"
Background="Green"
Foreground="White"
Text="{Binding SkinNumber}"></TextBlock>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Viewbox>
</Grid>
</Grid>
</Window>
Here is the code behind with the definitions of the Skin and Inning objects:
using System;
using System.Windows;
using System.ComponentModel;
using System.Collections.ObjectModel;
namespace WpfApplication3
{
public class Inning
{
private ObservableCollection<Skin> _skins = new ObservableCollection<Skin>();
public ObservableCollection<Skin> Skins
{
get { return _skins; }
set { _skins = value; }
}
}
public class Skin : INotifyPropertyChanged
{
public Skin()
{
}
public Skin( int skinNumber, Inning inning )
{
this.SkinNumber = skinNumber;
this.Inning = inning;
}
public Inning Inning { get; set; }
public int SkinNumber { get; set; }
public int SkinCount
{
get { return this.Inning.Skins.Count; }
}
public void Notify( string propertyName )
{
if ( PropertyChanged != null )
PropertyChanged( this, new PropertyChangedEventArgs( propertyName ) );
}
public event PropertyChangedEventHandler PropertyChanged;
}
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
}
}
The number of skins that can occur in an inning can change, and can be changed by the user, so I've put the ListViews into ViewBoxes so they automatically resize accordingly when the number of skins change. The resulting window can be seen here: http://i52.tinypic.com/244wqpl.jpg
I've tried all sorts of combinations of HorzontalAlignment="Stretch" and HorizontalContentAlignment="Stretch" and tried modifying the ItemsPanel template but I can't for the life of me seem to figure out how to get the ListView to stretch horizontally. Is what I'm trying to do impossible without some code behind to alter the width of the ListView dynamically? Or am I missing something really simple?
Any help that anyone can offer would be most appreciated.
Thanks,
Matthew
Try setting the ItemContainerStyle for your ListView to something like:
<ListView>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
</ListView.ItemContainerStyle>
</ListView>
You also might need to set <Viewbox Stretch="Fill"/>.
After this, I think you can remove all those other "HorizontalAlignment = Stretch" and "HorizontalContentAlignment = Stretch" setters in your code since it probably won't be necessary anymore.
Unexpectedly setting ScrollViewer.HorizontalScrollBarVisibility="Disabled" also worked for me:
<ListView ItemsSource="{Binding SourceList}"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
I have a class something like:
public class Section
{
private IEnumerable<Section> sections;
private IEnumerable<KeyValuePair<string, string>> attributes
public string Name {get;set;}
public IEnumerable<Section> Sections
{
get {return sections;}
}
public IEnumerable<KeyValuePair<string, string>> Attributes
{
get {return attributes;}
}
public Section(...)
{
//constructor logic
}
}
Which is contained in another class, lets call it OtherClass for sake of argument, that wraps around it and is used in WPF in an ObjectDataProvider.
As you can see, an instance of Section can contain many other instances of Section.
Is there a way in XAML to create a template that deals with this recursion?
This is what I've got so far:
<UserControl x:Class="OtherClassEditor"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:OtherClassNS="clr-namespace:NameSpace"
Height="300" Width="300">
<UserControl.Resources>
<ObjectDataProvider ObjectType="{x:Type OtherClassNS:OtherClass}" x:Key="ViewModel" />
<DataTemplate x:Key="listViewAttr">
<WrapPanel>
<TextBlock Text="{Binding Path=Key}"></TextBlock><TextBlock Margin="0,0,4,0">: </TextBlock>
<TextBlock Text="{Binding Path=Value}"></TextBlock>
</WrapPanel>
</DataTemplate>
<DataTemplate x:Key="listViewSection">
<StackPanel>
<WrapPanel Margin="0,0,0,8">
<TextBlock Margin="0,0,4,0">Section:</TextBlock>
<TextBlock Text="{Binding Path=Name}"/>
</WrapPanel>
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="listViewData">
<StackPanel>
<WrapPanel Margin="0,0,0,8">
<TextBlock Margin="0,0,4,0">Section: </TextBlock>
<TextBlock Text="{Binding Path=Name}"/>
<ListView DataContext="{Binding Path=Sections}" ItemTemplate="{StaticResource listViewSection}" ItemsSource="{Binding Sections}">
</ListView>
<ListView DataContext="{Binding Path=Attributes}" ItemsSource="{Binding Attributes}" ItemTemplate="{StaticResource listViewAttr}">
</ListView>
</WrapPanel>
</StackPanel>
</DataTemplate>
</UserControl.Resources>
<Grid>
<ListView DataContext="{StaticResource ViewModel}" ItemTemplate="{StaticResource listViewData}" ItemsSource="{Binding Sections}">
</ListView>
</Grid>
</UserControl>
But I can't get recursion, as a DataTemplate can only reference one that is declared before it.
Can this be done in XAML? If so, how? Is this something that I'll have to do in code behind?
Are DataTemplates even the way to go? Is there a better way to display and edit this data?
In case anyone needs to see how to do this without using an HierarchicalDataTemplate:
<UserControl x:Class="OtherClassEditor"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:OtherClassNS="clr-namespace:NameSpace"
Height="300" Width="300">
<UserControl.Resources>
<ObjectDataProvider ObjectType="{x:Type OtherClassNS:OtherClass}" x:Key="ViewModel" />
<DataTemplate x:Key="listViewAttr">
<WrapPanel>
<TextBlock Text="{Binding Path=Key}"></TextBlock>
<TextBlock Margin="0,0,4,0">: </TextBlock>
<TextBlock Text="{Binding Path=Value}"></TextBlock>
</WrapPanel>
</DataTemplate>
<DataTemplate x:Key="listViewData">
<StackPanel>
<WrapPanel Margin="0,0,0,8">
<TextBlock Margin="0,0,4,0">Section: </TextBlock>
<TextBlock Text="{Binding Path=Name}"/>
</WrapPanel>
<ListView ItemTemplate="{DynamicResource listViewData}" ItemsSource="{Binding Sections}" />
<ListView ItemsSource="{Binding Attributes}" ItemTemplate="{StaticResource listViewAttr}" />
</StackPanel>
</DataTemplate>
</UserControl.Resources>
<Grid>
<ListView DataContext="{StaticResource ViewModel}" ItemTemplate="{DynamicResource listViewData}" ItemsSource="{Binding Sections}">
</ListView>
</Grid>
</UserControl>
This gets me basically what I want.
The main change is as Dan Bryant suggested: changing the ItemTemplate to use a Dynamic rather than static resource for the recursive object (Section).
Perhaps I'm misunderstanding your scenario, but is HierarchicalDataTemplate what you're looking for?
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.