简体   繁体   中英

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

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}" ...>

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>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM