如何从DataTemplate访问ObservableCollection

时间:2015-04-06 17:59:11

标签: c# wpf

我想从我的新ObservableCollection访问我的商品DataTemplate,我的实际DataTemplate出了什么问题?

有我的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>

我的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
}

正如您在代码中看到的,我正在为ListView创建视图。一个带有图标和文字,另一个带有一些细节(尚未完成)。

你能帮助我吗?

谢谢

2 个答案:

答案 0 :(得分:1)

您为ContentTemplate设置ContentControl但是没有显示Content的时刻。最简单的解决方案是将当前DataContext绑定到Content

<ContentControl Content="{Binding}" Style="{StaticResource selectableContentStyle}" ...>

答案 1 :(得分:0)

您可以将ElementBinding与Window DataContext一起使用。创建窗口名称为win并尝试将其DataContext.Items绑定到DataTemplate内ListBox的ItemsSource。请参阅下面的代码。

<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>