Reputation:
I want to access my item ObservableCollection
from my new DataTemplate
, what's wrong with my actual DataTemplate
?
There is my xaml:
<Window x:Class="Data.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Data"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<!-- Icon template style -->
<DataTemplate x:Key="iconTemplate">
<ListView ItemsSource="{Binding Items}">
<ListView.ItemTemplate>
<DataTemplate>
<DockPanel>
<TextBlock DockPanel.Dock="Bottom" Text="{Binding Name}"/>
<Rectangle Height="32" Width="32" Fill="Blue"/>
</DockPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</DataTemplate>
<!-- Detailed list style-->
<DataTemplate x:Key="listTemplate">
</DataTemplate>
<Style x:Key="selectableContentStyle" TargetType="{x:Type ContentControl}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=TTemplate}" Value="Icon">
<Setter Property="ContentTemplate" Value="{StaticResource iconTemplate}" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=TTemplate}" Value="List">
<Setter Property="ContentTemplate" Value="{StaticResource listTemplate}" />
</DataTrigger>
<!-- Other listview styles -->
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<StackPanel>
<Button Command="{Binding ChangeView}">Change</Button>
</StackPanel>
<ContentControl Style="{StaticResource selectableContentStyle}" Margin="112,66,189.4,84.8"/>
</Grid>
</Window>
And my viewmodel:
public class Model
{
public String Name { get; set; }
public Int32 Length { get; set; }
public BitmapSource Image { get; set; }
}
public enum TestTemplate
{
Icon,
List
}
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
public class RelayCommand : ICommand
{
public RelayCommand(Action<object> execute)
: this(execute, null)
{
}
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute(parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter)
{
_execute(parameter);
}
private readonly Action<object> _execute;
private readonly Predicate<object> _canExecute;
}
public class ViewModel : ViewModelBase
{
#region FIELDS
#endregion
#region PROPERTIES
private TestTemplate template;
public TestTemplate TTemplate
{
get
{
return this.template;
}
set
{
this.template = value;
this.NotifyPropertyChanged("TTemplate");
}
}
public ICommand ChangeView { get; set; }
public ObservableCollection<Model> Items
{
get
{
return this.items;
}
set
{
this.items = value;
this.NotifyPropertyChanged("Items");
}
}
private ObservableCollection<Model> items;
#endregion
#region CONSTRUCTORS
/// <summary>
/// Creates a new ViewModel instance
/// </summary>
public ViewModel()
{
this.TTemplate = TestTemplate.Icon;
this.ChangeView = new RelayCommand((param) => this.ChangeViewAction(param));
this.Items = new ObservableCollection<Model>();
this.Items.Add(new Model()
{
Name = "test",
Length = 1
});
this.Items.Add(new Model()
{
Name = "test2",
Length = 2
});
}
#endregion
#region METHODS
private void ChangeViewAction(Object param)
{
if (this.TTemplate == TestTemplate.Icon)
{
this.TTemplate = TestTemplate.List;
}
else
{
this.TTemplate = TestTemplate.Icon;
}
}
#endregion
}
As you can see with the code, i'm creating views for a ListView. One with icons and text and the other with some details (not done yet).
Can you help me ?
Thank you
Upvotes: 1
Views: 160
Reputation: 33384
Ate the moment you set ContentTemplate
for ContentControl
but it has no Content
to display. Easiest solution is to bind current DataContext
to Content
<ContentControl Content="{Binding}" Style="{StaticResource selectableContentStyle}" ...>
Upvotes: 1
Reputation: 5366
You can use ElementBinding with Window DataContext. Created window name as win and try to bind it DataContext.Items to the ItemsSource of the ListBox inside the DataTemplate Refer below code.
<Window x:Class="Icon_Learning.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Icon_Learning" x:Name="win"
Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded">
<Window.Resources>
<!-- Icon template style -->
<DataTemplate x:Key="iconTemplate" >
<ListBox ItemsSource="{Binding ElementName=win,Path=DataContext.Items}" Background="AliceBlue">
<ListBox.ItemTemplate>
<DataTemplate DataType="{x:Type local:Model}">
<DockPanel>
<TextBlock DockPanel.Dock="Bottom" Text="{Binding Name}"/>
<Rectangle Height="32" Width="32" Fill="Blue"/>
</DockPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DataTemplate>
<!-- Detailed list style-->
<DataTemplate x:Key="listTemplate">
<ListBox ItemsSource="{Binding ElementName=win,Path=DataContext.Items}" Background="AliceBlue">
<ListBox.ItemTemplate>
<DataTemplate DataType="{x:Type local:Model}">
<DockPanel>
<TextBlock DockPanel.Dock="Bottom" Text="{Binding Name}"/>
<Rectangle Height="32" Width="32" Fill="Red"/>
</DockPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DataTemplate>
<Style x:Key="selectableContentStyle" TargetType="{x:Type ContentControl}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=TTemplate}" Value="Icon">
<Setter Property="ContentTemplate" Value="{StaticResource iconTemplate}" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=TTemplate}" Value="List">
<Setter Property="ContentTemplate" Value="{StaticResource listTemplate}" />
</DataTrigger>
<!-- Other listview styles -->
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<StackPanel>
<Button Command="{Binding ChangeView}">Change</Button>
</StackPanel>
<ContentControl Style="{StaticResource selectableContentStyle}" Margin="112,66,189.4,84.8"/>
</Grid>
Upvotes: 0