user4717662
user4717662

Reputation:

How can I access ObservableCollection from a DataTemplate

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

Answers (2)

dkozl
dkozl

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

Ayyappan Subramanian
Ayyappan Subramanian

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

Related Questions